#Vue.js hello world
Explore tagged Tumblr posts
Text
Master JavaScript: Step-by-Step Tutorial for Building Interactive Websites
JavaScript Tutorial

Master JavaScript: Step-by-Step Tutorial for Building Interactive Websites
In the evolving world of web development, JavaScript remains one of the most powerful and essential programming languages. Whether you're building simple webpages or full-fledged web applications, JavaScript gives life to your content by making it interactive and dynamic. This JavaScript Tutorial offers a beginner-friendly, step-by-step guide to help you understand core concepts and begin creating responsive and engaging websites.
What is JavaScript?
JavaScript is a lightweight, high-level scripting language primarily used to create dynamic and interactive content on the web. While HTML structures the webpage and CSS styles it, JavaScript adds interactivity—like handling clicks, updating content without refreshing, validating forms, or creating animations.
Initially developed for client-side scripting, JavaScript has evolved significantly. With the rise of environments like Node.js, it is now also used for server-side programming, making JavaScript a full-stack development language.
Why Learn JavaScript?
If you're looking to become a front-end developer or build web-based applications, JavaScript is a must-have skill. Here’s why:
It runs on all modern browsers without the need for plugins.
It’s easy to learn but incredibly powerful.
It works seamlessly with HTML and CSS.
It powers popular frameworks like React, Angular, and Vue.js.
It’s in high demand across the tech industry.
This JavaScript Tutorial is your gateway to understanding this versatile language and using it effectively in your web projects.
Getting Started: What You Need
To start coding in JavaScript, all you need is:
A modern browser (like Chrome or Firefox)
A text editor (such as Visual Studio Code or Sublime Text)
Basic knowledge of HTML and CSS
No complex setups—just open your browser and you're ready to go!
Step 1: Your First JavaScript Code
JavaScript code can be embedded directly into HTML using the <script> tag.
Example:<!DOCTYPE html> <html> <head> <title>JavaScript Demo</title> </head> <body> <h1 id="demo">Hello, World!</h1> <button onclick="changeText()">Click Me</button> <script> function changeText() { document.getElementById("demo").innerHTML = "You clicked the button!"; } </script> </body> </html>
Explanation:
The onclick event triggers the changeText() function.
document.getElementById() accesses the element with the ID demo.
.innerHTML changes the content of that element.
This simple example showcases how JavaScript can make a static HTML page interactive.
Step 2: Variables and Data Types
JavaScript uses let, const, and var to declare variables.
Example:let name = "Alice"; const age = 25; var isStudent = true;
Common data types include:
Strings
Numbers
Booleans
Arrays
Objects
Null and Undefined
Step 3: Conditional Statements
JavaScript allows decision-making using if, else, and switch.let age = 20; if (age >= 18) { console.log("You are an adult."); } else { console.log("You are a minor."); }
Step 4: Loops
Use loops to execute code repeatedly.for (let i = 0; i < 5; i++) { console.log("Iteration:", i); }
Other types include while and do...while.
Step 5: Functions
Functions are reusable blocks of code.function greet(name) { return "Hello, " + name + "!"; } console.log(greet("Alice")); // Output: Hello, Alice!
Functions can also be anonymous or arrow functions:const greet = (name) => "Hello, " + name;
Step 6: Working with the DOM
The Document Object Model (DOM) allows you to access and manipulate HTML elements using JavaScript.
Example: Change element style:document.getElementById("demo").style.color = "red";
You can add, remove, or change elements dynamically, enhancing user interaction.
Step 7: Event Handling
JavaScript can respond to user actions like clicks, keyboard input, or mouse movements.
Example:document.getElementById("myBtn").addEventListener("click", function() { alert("Button clicked!"); });
Step 8: Arrays and Objects
Arrays store multiple values:let fruits = ["Apple", "Banana", "Mango"];
Objects store key-value pairs:let person = { name: "Alice", age: 25, isStudent: true };
Real-World Applications of JavaScript
Now that you have a basic grasp, let’s explore how JavaScript is used in real-life projects. The applications of JavaScript are vast:
Interactive Websites: Menus, image sliders, form validation, and dynamic content updates.
Single-Page Applications (SPAs): Tools like React and Vue enable dynamic user experiences without page reloads.
Web Servers and APIs: Node.js allows JavaScript to run on servers and build backend services.
Game Development: Simple 2D/3D browser games using HTML5 Canvas and libraries like Phaser.js.
Mobile and Desktop Apps: Frameworks like React Native and Electron use JavaScript for cross-platform app development.
Conclusion
Through this JavaScript Tutorial, you’ve taken the first steps in learning a foundational web development language. From understanding what is javascript is now better.
As you continue, consider exploring advanced topics such as asynchronous programming (promises, async/await), APIs (AJAX, Fetch), and popular frameworks like React or Vue.
0 notes
Text
Website Developer in Bangalore: Hello Errors Delivers More Than Just Code

In today’s digital-first economy, your website is often the first impression your brand makes. Whether you’re a fast-growing startup or a legacy business pivoting online, having a professional, performance-driven website is no longer optional—it's critical. And if you're based in India’s tech capital, the search for the right Website Developer in Bangalore ends at Hello Errors.
Bangalore is not only home to IT giants and unicorn startups but also a vibrant ecosystem of SMEs, creators, and emerging brands. What they all have in common is the need for a modern, engaging, and scalable online presence. That’s where Hello Errors steps in as your digital partner—not just another development agency, but a full-spectrum digital solutions company that crafts websites designed for success.
Why Businesses in Bangalore Need Specialized Website Developers
With consumers relying on digital platforms to discover, evaluate, and engage with businesses, having a strong online foundation is crucial. Here’s why choosing a Website Developer in Bangalore with local and global expertise makes a difference:
Bangalore-based developers understand regional consumer behavior
Faster turnaround and easier communication with local teams
Adaptability to Indian and international tech regulations
On-the-ground collaboration and faster iterations
Hello Errors brings the best of both worlds—deep local insight and cutting-edge global tech capabilities—to help your business thrive online.
Industry-Specific Website Development: One Size Doesn’t Fit All
One key reason Hello Errors is a top-rated Website Developer in Bangalore is its industry-focused approach. The team doesn’t believe in cookie-cutter templates. Instead, they tailor development strategies to suit the unique needs of various industries.
📚 EdTech Portals
Hello Errors creates dynamic learning portals with course management, video hosting, assessments, and secure login systems.
🛍️ E-commerce
Scalable online stores with real-time inventory, multiple payment gateways, and SEO-optimized product pages.
🏥 Healthcare
HIPAA-compliant websites with features like appointment booking, telemedicine integration, and health blogs.
🧑💼 Corporate Websites
Clean, functional, and fast-loading websites designed to reflect professionalism and brand authority.
Whether you're a D2C brand or a SaaS platform, Hello Errors ensures your website speaks directly to your target audience.
Technologies That Scale With Your Business
What truly separates Hello Errors from other Website Developers in Bangalore is their use of modern, scalable, and future-proof technologies. They don’t just build for today—they build for what your business will become tomorrow.
🧱 Tech Stack Highlights:
Frontend: React.js, Vue.js, Next.js
Backend: Node.js, Django, PHP, Laravel
CMS: WordPress, Webflow, Shopify (customized)
Databases: MongoDB, MySQL, PostgreSQL
Cloud: AWS, Google Cloud, DigitalOcean
Their developers choose the right combination of tools and frameworks based on your goals, budget, and scalability needs. This forward-thinking approach ensures your site grows as your business does.
The Hidden Power of Post-Launch Support
Many businesses think their job is done once the website is live. That’s a myth. Post-launch support is what keeps your digital investment secure, optimized, and relevant.
As your trusted Website Developer in Bangalore, Hello Errors offers ongoing services such as:
Security monitoring and bug fixes
Performance tuning and page speed optimization
Content and SEO updates
New feature rollouts
Analytics integration and reporting
With Hello Errors, you’re never left stranded. They grow with you, constantly iterating and improving based on user feedback and analytics.
SEO-First Development: Visibility Built-In
Your website could be a visual masterpiece—but if it’s not ranking on search engines, it won’t matter. That’s why Hello Errors builds SEO directly into the development process.
Unlike many agencies that treat SEO as an afterthought, Hello Errors includes:
Clean code structure and semantic HTML
Mobile responsiveness and fast loading times
Keyword optimization across meta tags and content
Schema markup for rich snippets
URL structure and sitemap optimization
This ensures your website isn’t just pretty—it’s found by the right people at the right time.
Real Collaboration, Not Just Client Work
At Hello Errors, collaboration is more than a buzzword—it’s a practice. When you hire them as your Website Developer in Bangalore, you become a partner in the development journey.
Their process includes:
Workshops to understand your business goals
Wireframe design and UX mapping
Agile sprints and frequent check-ins
Transparent communication and delivery milestones
This level of client involvement leads to better alignment, faster feedback loops, and a product that genuinely reflects your brand.
What Makes Hello Errors the Go-To Website Developer in Bangalore?
Let’s recap what makes Hello Errors your ideal web development partner:
🛠️ Full-stack development expertise
🎨 UI/UX-focused design thinking
🚀 SEO-first development methodology
🤖 Integration of AI, ML, and app features
🔄 Continuous post-launch support
🧠 Industry-specific customizations
📍 Bangalore-based team with global quality
Whether you’re looking for a full-fledged business website, a scalable web app, or a platform that integrates seamlessly with mobile, Hello Errors brings precision, performance, and passion to every project.
Ready to Build a High-Performance Website in Bangalore?
Your business deserves more than a basic website. It needs a digital experience that resonates, converts, and scales. As a trusted Website Developer in Bangalore, Hello Errors delivers websites that combine form, function, and future-readiness.
📞 Contact Hello Errors today at https://helloerrors.in Let’s build something exceptional—together.
#WebsiteDeveloperInBangalore#HelloErrors#WebDevelopmentBangalore#SEOWebsiteDeveloper#UXUIDesign#ResponsiveWebDevelopment#TopDeveloperInBangalore#DigitalTransformationIndia#CustomWebsiteDesign#StartupWebSolutions
0 notes
Text
React vs Vue vs Angular: Which One Should You Use in 2025
Overview: (React)
React continues to dominate the frontend development world in 2025, offering developers unmatched flexibility, performance, and community support. Built and maintained by Meta (formerly Facebook), React has matured into a robust UI library that startups and tech giants use.
What Is React?
React is an open-source JavaScript library designed for building fast, interactive user interfaces, primarily for single-page applications (SPAs). It's focused on the "View" layer of web apps, allowing developers to build encapsulated, reusable components that manage their state.
With the release of React 18 and innovations like Concurrent Rendering and Server Components, React now supports smoother UI updates and optimized server-side rendering, making it more future-ready than ever.
Key Aspects
Component-Based Architecture: React's modular, reusable component structure makes it ideal for building scalable UIs with consistent patterns.
Blazing-Fast UI Updates: Thanks to the virtual DOM, React efficiently updates only what's changed, ensuring smooth performance even in complex apps.
Hooks and Functional Components: With modern features like React Hooks, developers can manage state and lifecycle behavior cleanly in functional components—there is no need for class-based syntax.
Concurrent Rendering: React 18 introduced Concurrent Mode, improving performance by rendering background updates without blocking the main thread.
Massive Ecosystem: From Next.js for SSR to React Native for mobile apps, React integrates with an enormous ecosystem of tools, libraries, and extensions.
Code: App.jsx
Import React from 'react';
function App() {
return (
<div>
<h1>Hello, World! </h1>
</div>
);
}
export default App;
Entry Point: main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
HTML Template: index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/main.jsx"></script>
</body>
</html>
Overview (Aue)
Vue.js continues to be a strong contender in the frontend framework space in 2025, primarily for developers and teams seeking simplicity without sacrificing power. Created by Evan You, Vue has grown into a mature framework known for its clean syntax, detailed documentation, and ease of integration.
What Is Vue?
Vue is a progressive JavaScript framework for building web user interfaces. Its design philosophy emphasizes incrementality—you can use Vue for a small feature on a page or scale it up into a full-fledged single-page application (SPA).
With Vue 3 and the Composition API, Vue has evolved to offer better modularity, TypeScript support, and reusability of logic across components.
Key Aspects
Lightweight and Fast: Vue has a small footprint and delivers high performance out of the box. It's fast to load, compile, and render, making it an excellent choice for performance-sensitive projects.
Simple Integration: Vue can be dropped into existing projects or used as a complete app framework. It works well with legacy systems and new apps alike.
Easy to Learn: Vue's gentle learning curve and readable syntax make it a top choice for beginners and teams with mixed skill levels.
Composition API: The Composition API in Vue 3 allows for better code reuse and more scalable application architecture, similar to React's hooks.
Code: App.vue
<template>
<div>
<h1>Hello, World! </h1>
</div>
</template>
<script setup>
</script>
<style scoped>
h1 {
color: #42b983;
}
</style>
Entry Point: main.js
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
HTML Template: index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>
Overview (Angular)
Angular, developed and maintained by Google, remains a top choice for enterprise-level applications in 2025. As a fully integrated framework, Angular provides all the tools a development team needs to build large-scale, maintainable apps out of the box.
What Is Angular?
Angular is a TypeScript-based frontend framework that includes built-in solutions for routing, state management, HTTP communication, form handling, and more. Unlike React or Vue, Angular is opinionated and follows strict architectural patterns.
Angular 17 (and beyond) introduces Signals, a new reactive system designed to improve state management and performance by offering more predictable reactivity.
Key Aspects:
All-in-One Framework: Angular offers everything you need—from routing to testing—without needing third-party libraries. This consistency is great for large teams.
Strong Typing with TypeScript: TypeScript is the default language in Angular, making it ideal for teams that prioritize type safety and tooling.
Ideal for Enterprises: With its structured architecture, dependency injection, and modular system, Angular is built for scalability, maintainability, and long-term project health.
Improved Performance: Angular 17 introduces Signals, improving reactive programming, rendering speed, and resource efficiency.
Angular Drawbacks
A steep learning curve due to its complex concepts like decorators, DI, zones, etc.
More verbose code compared to Vue and React.
Slower adoption in smaller teams and startups.
Project Setup:
bash
Copy
Edit
ng new hello-world-app
cd hello-world-app
ng serve
Component: app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `<h1>Hello, World! </h1>`,
styles: [`h1 { color: #dd0031; }`]
})
export class AppComponent {}
Module: app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
bootstrap: [AppComponent]
})
export class AppModule {}
Entry Point: main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Which One Should Use
If you're looking for simplicity and speed, especially as a solo developer or on smaller projects, Vue.js is your best bet. Its gentle learning curve and clean syntax make it ideal for quick development and maintainable code.
For scalable, dynamic applications, React strikes the perfect balance. It offers flexibility, a vast ecosystem, and strong community support, making it a top choice for startups, SaaS products, and projects that may evolve over time.
If you're building large-scale, enterprise-grade apps, Angular provides everything out of the box—routing, forms, state management—with a highly structured approach. It's TypeScript-first and built for long-term maintainability across large teams.
In short:
Choose Vue for ease and speed.
Choose React for flexibility and modern workflows.
Choose Angular for structure and enterprise power.
0 notes
Text
Hire Dedicated Developers: What You Need to Know Before You Start
Hello Everyone!
There’s no doubt that an efficient software development team has become the core of businesses across the world. This is because developing apps and websites that are user-friendly and smooth attracts potential consumers, thus generating revenue and profitability.
It doesn’t matter whether you’re a startup or an established enterprise, in today’s time of technology, you should hire dedicated developers to scale your venture. But how do you figure it out? How do you find the best and most affordable developers to work on your dream project? The answer is simple - hire developers in India. Trust me when I say this, I’ve worked with developers across the globe but didn’t better value for money anywhere else.
For instance, when you hire remote developers from India, they not only offer you global expertise but also provide those services at a fraction of the cost that you might spend to hire dedicated developers in your home country.
In this blog, I’ll talk about everything you need to know before you hire dedicated developers from India. By the end, I’ll also share some secret tips with you that’ll help you choose the software developer that will perfectly fit your requirements. Let’s get started!
Know What It Means to Hire Dedicated Developers from India
First, let’s break down what it means to hire dedicated developers for your project. Unlike freelancers who work on a project basis or in-house developers you manage full-time, when you hire dedicated developers from India, they are typically part of an outsourced team. They’re focused solely on your project for the duration of the contract, essentially becoming an extension of your business.
This setup gives you the flexibility to scale your development team quickly while benefiting from specialized expertise when you hire remote developers. It’s perfect for long-term projects where continuity, knowledge retention, and collaboration are critical.
Process to Hire Dedicated Developers from India
I’m sure after understanding the benefits of when you hire developers in India, you’d be curious to know how you can go about the process. Don’t worry, I’ve got you covered. The following are the 5 simple steps you need to follow in order to hire remote developers from India for your project :
1. Define Your Project Requirements Clearly
Before you even start looking for developers, it’s essential to have a clear understanding of what you need and why you want to hire dedicated developers for your project. I’ve curated a list of questions you should ask yourself before you decide to hire developers in India for your project -
What type of project am I building? Is it a mobile app, website, software solution, or something else?
What is my budget? What is the financial range that I want to have to hire developers in India?
Which tech stack do I need expertise in? Do I need to hire developers in India proficient in specific languages like Java, Python, Swift, or frameworks like React, Angular, or Vue.js?
What is the project timeline? Do I need developers for a one-time project, or will this be an ongoing, long-term collaboration?
What level of experience am I looking for? Do I need senior developers with advanced expertise, or will mid-level or junior developers suffice?
How will the developers collaborate with my in-house team? What kind of communication and project management tools should be in place?
Once you have your requirements nailed down, you'll know what skills and experience to look for.
2. Look for Companies that Help You Hire Dedicated Developers from India
Once you’re clear with what you’re looking for, the next step for you would be to look for software development outsourcing companies that help you hire remote developers from India.
When you’re ready to hire developers in India or anywhere else, it’s important to do thorough research. There are plenty of development agencies and platforms out there, but not all are created equal. Look for companies with proven experience, a strong portfolio, and positive client reviews. Following are the points you should research while you’re looking for agencies to help you hire dedicated developers –
Company Reputation and Client Reviews
Look for agencies to hire developers in India with positive reviews and testimonials from past clients. Explore online platforms like Clutch, GoodFirms, or Google Reviews to get an unbiased view of their reliability and professionalism.
Experience and Expertise in Relevant Technologies
Ensure the agency has a proven track record in the technologies and development frameworks you need. Check their case studies and portfolio to confirm their expertise in projects similar to yours.
Team Size and Developer Availability
Research the agency’s team size and structure. Can they provide the necessary number of developers for your project, and are they available within your timeline?
Do They Provide a Dedicated Project Manager?
Trust me, having a dedicated project manager is one of the most important points to consider when you hire remote developers. This is because they facilitate clear communication and avoid any chances of miscommunication.
Understand the Engagement Models The Outsourcing Company Offers
It’s important to figure out what are the engagement models that your hiring partner is providing you. Companies like Resourcifi offer full-time, part-time, and hourly models so that you can choose what suits your needs the best.
3. Evaluate Technical Skills of the Talent When You Hire Remote Developers From India
Once you’ve shortlisted potential partners, it’s time to dig deeper into the technical capabilities of the talent they are offering. You can ask the hiring partners to provide you with the video CVs of the developers, work samples, and their expertise in technologies relevant to your project.
Secret Tip - Some companies like Resourcifi also provide you with free one-week trial when you hire dedicated developers with them. This can assure you of the experience of the developer, avoiding any risks of spending your hard-earned money on developers that might not align with your requirements.
4. Check Communication and Collaboration Tools
A successful development project depends heavily on clear communication. Since you’ll be working with remote developers, it’s important to establish how you'll stay in touch when you hire dedicated developers.
Ask potential partners about the tools they use for project management and communication—Slack, Zoom, Jira, or Trello are all common options. Make sure you’re comfortable with their processes and availability across different time zones as well.
Secret Tip - You can have overlapping working hours when you hire dedicated developers from India. This can-do wonders for your team as the team in your home country can seamlessly handover the pending tasks to the offshore developers at the end of their day, so that they can work overnight on your project. This is my favorite tip as it ensures round-the-clock productivity and your project keeps on progressing even when you’re sleeping!
5. Set Expectations Early
At last, to avoid misunderstandings later on, be crystal clear about your expectations when you hire dedicated developers from day one. Discuss project timelines, milestones, and deliverables. Setting clear goals from the beginning ensures that everyone is on the same page.
Conclusion: Is Hiring Dedicated Developers Right for You?
In conclusion, hiring dedicated developers offers immense benefits—expertise, flexibility, and cost-effectiveness. However, it’s crucial to approach the process with clear expectations, strong communication, and a focus on quality.
If you’re looking for long-term development partners and want to scale efficiently, dedicated developers might be exactly what your business needs. And if you’re considering outsourcing, don’t overlook the option to hire developers in India. The combination of cost efficiency and technical expertise makes it a great choice.
Whether you need to hire remote developers or build a specialized team, make sure to do your homework—and you’ll be well on your way to a successful partnership!
0 notes
Text
Hello Coding - Anyone Can Learn to Code! 550+ Hours of Content!

"Hello Coding: Anyone Can Learn to Code!" is an expansive online course designed to introduce and deepen understanding of computer programming for individuals at all skill levels. With over 550 hours of meticulously curated content, the course aims to transform beginners into proficient coders and to help experienced programmers refine and expand their skills.
Course Structure and Content
The course is structured to cover a broad range of programming topics and languages. Starting from the basics, it gradually progresses to more complex concepts, ensuring that learners build a solid foundation before tackling advanced subjects. Key areas covered include web development, mobile app development, data science, and game development, among others.
Introduction to Programming: The course begins with an introduction to programming fundamentals. It covers the basic principles of coding, such as variables, control structures, functions, and data types. This section is designed to be accessible to complete novices, with no prior experience required.
Web Development: This segment delves into HTML, CSS, and JavaScript, teaching learners how to create and style web pages. It also covers popular frameworks and libraries like React, Angular, and Vue.js, which are essential for modern front-end development. On the back-end side, it explores server-side languages like Node.js, Python, and PHP, along with databases such as SQL and MongoDB.
Mobile App Development: Learners are introduced to mobile app development for both Android and iOS platforms. The course covers native app development using Swift for iOS and Kotlin for Android. It also explores cross-platform development frameworks like Flutter and React Native, which allow developers to create apps that work on multiple operating systems from a single codebase.
Data Science and Machine Learning: For those interested in data science, the course offers comprehensive modules on Python, R, and various data analysis libraries and tools. It covers data visualization, statistical analysis, and machine learning algorithms. This section is ideal for learners who wish to pursue careers in data science or integrate data-driven decision-making into their existing skill set. You can also try this HELLO CODING
Game Development: The course includes modules on game development using popular engines like Unity and Unreal Engine. It covers the basics of game design, programming, and the creation of both 2D and 3D games. This segment is particularly appealing to creative individuals who want to bring their game ideas to life.
Learning Approach
"Hello Coding" adopts a project-based learning approach. This means that instead of just theoretical learning, students engage in hands-on projects that allow them to apply what they have learned. These projects range from simple exercises to complex applications, ensuring that learners can see the real-world applications of their coding skills.
The course also emphasizes interactive learning. Through coding challenges, quizzes, and peer interactions, learners are encouraged to test their knowledge and learn from others. This interactive environment helps to reinforce learning and fosters a sense of community among participants.
Support and Resources
Learners have access to a wealth of resources to support their learning journey. These include detailed video tutorials, comprehensive reading materials, and practical coding exercises. Additionally, the course provides access to mentors and instructors who can offer guidance and answer questions.
Career Preparation
One of the standout features of "Hello Coding" is its focus on career preparation. The course includes modules on resume building, portfolio development, and interview preparation. This ensures that learners are not only equipped with technical skills but are also prepared to enter the job market with confidence.
Conclusion you can also try this HELLO CODING
"Hello Coding: Anyone Can Learn to Code!" is an all-encompassing course that caters to a wide audience, from complete beginners to experienced developers. Its extensive content, project-based approach, and focus on career preparation make it an invaluable resource for anyone looking to start or advance their coding journey. With over 550 hours of content, learners have the opportunity to explore various fields within programming, find their niche, and build a successful career in the tech industry.
DISCLAIMER
There is an affiliate link for a best product in this article which may make some profit for me
0 notes
Text
The Rise of Web Components: A Comprehensive Guide for Front-End Developers
Introduction
Developing modern, effective, and maintainable web applications requires staying ahead of the curve in the ever changing field of web development. The use of web components is one of the most recent innovations that is becoming popular in the front-end development community. We will examine the emergence of web components, their advantages, their creation and application processes, and their influence on the direction of web development in this extensive book.
Comprehending Web Components
Web components are a collection of web platform APIs that enable developers to design encapsulated, configurable, and reusable web application components. These comprise Custom Elements, Shadow DOM, HTML Templates, and HTML Imports as its four primary components.
1.Custom Elements: Developers are allowed to define their own HTML elements with unique behaviours thanks to Custom Elements. This makes it possible to create reusable parts that fit into any website with ease.
2.Shadow DOM: By building a scoped subtree of DOM elements and styles, Shadow DOM encapsulates web components. By doing this, you can make sure that styles and functions that are defined inside a web component stay contained and don’t affect other parts of the website.
3.HTML Templates: These allow you to define HTML sections that may be copied and added to the Document Object Model (DOM) as needed. This is helpful for building data-populated component structures that are reusable and dynamic.
4.HTML Imports: With HTML Imports, web component developers can include external HTML pages as dependencies. This facilitates the management of dependencies and the reuse of components in other projects.
Advantages of Web Elements Front-end developers and web applications can benefit from the following when using web components:
1.Reusability: By encapsulating functionality into self-contained components that are readily reused across several projects, web components facilitate code reusability.
2.Encapsulation: Web components are protected from styles and functionality leaking out and clashing with other areas of the page by the shadow DOM.
3.Maintainability: Developers can design more manageable and modular codebases, which facilitate the management and updating of large-scale web applications, by encapsulating functionality and styling within web components.
4.Interoperability: Web components are compatible with current web frameworks and libraries since they are constructed using common web technologies like HTML, CSS, and JavaScript.
Creating and Using Web Components: The process of creating and utilising web components is simple and may be carried out with either standard JavaScript or well-known front-end frameworks such as Angular, React, or Vue.js. This is a simple illustration of how to make and utilise a unique web component:
<!DOCTYPE html> <html> <head> <title>Web Component Example</title> <script> // Define a new custom element class MyComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: ‘open’ }); this.shadowRoot.innerHTML = ` <style> /* Styles scoped to the shadow DOM */ :host { display: block; padding: 1rem; background-color: lightblue; } </style> <p>Hello, World!</p> `; } } // Register the custom element customElements.define(‘my-component’, MyComponent); </script> </head> <body> <! — Use the custom element → <my-component></my-component> </body> </html>
Future of Web Development Web components are expected to have a big impact on the field as long as they continue to gain traction and browser support keeps getting better. Web components are a great way to create scalable, maintainable, and effective modern web applications because of their focus on interoperability, encapsulation, and reusability.
Conclusion Front-end developers’ approach to creating web applications has significantly changed as a result of the emergence of web components. Web components provide a potent way to build contemporary, maintainable, and scalable web applications by adopting the concepts of reusability, encapsulation, and interoperability. Web components are expected to become a crucial component of the web development toolkit as browser support advances and usage rises, influencing the direction of web development for Years to come.
Ready to dive deeper into the world of web development? Enhance your skills and stay ahead of the curve with our comprehensive Front end developer course at LearNowX. Whether you’re just starting out or looking to level up your expertise, our course covers everything you need to know about web components and much more. Don’t miss out on this opportunity to elevate your career in web development. Enroll now at LearNowX and become a master front end developer!
0 notes
Text
Essential Skills for Full-Stack Developers in 2023
Hello everyone. In the fast-paced world of technology, the role of a full-stack developer continues to evolve.

1. Proficiency in Modern Front-End Frameworks:
As a full-stack developer, you should have a strong grasp of modern front-end frameworks. In 2023, this includes frameworks like React, Angular, and Vue.js. These tools help you create dynamic and responsive user interfaces, which are in high demand for web and mobile applications.
2. Mastery of Serverless Architecture:
Serverless architecture is gaining popularity for its scalability and cost-effectiveness. Full-stack developers should understand how to work with serverless platforms like AWS Lambda, Azure Functions, or Google Cloud Functions. This knowledge will enable you to build efficient and cost-effective back-end systems.
3. Microservices and Containers:
In the world of back-end development, microservices and containerization are becoming increasingly important. Knowledge of containerization tools like Docker and container orchestration platforms such as Kubernetes is essential for deploying and managing microservices.
4. GraphQL:
GraphQL is a query language for APIs that offers more flexibility compared to traditional REST APIs. Understanding and working with GraphQL is a valuable skill for full-stack developers, as it allows you to efficiently fetch and manage data for your applications.
5. Progressive Web Apps (PWAs):
PWAs are web applications that provide a native app-like experience on the web. Full-stack developers should know how to build and optimize PWAs for improved performance and user engagement.
6. DevOps and CI/CD:
Continuous Integration and Continuous Deployment (CI/CD) practices are essential for streamlining the development and deployment processes. Full-stack developers should be comfortable with tools like Jenkins, GitLab CI, or GitHub Actions to automate testing and deployment.
7. Front-end Performance Optimization:
In 2023, user experience will remain a top priority. Knowledge of front-end performance optimization techniques, such as lazy loading, image compression, and code splitting, is vital for delivering fast and efficient web applications.
8. Cross-Platform Development:
Understanding cross-platform development frameworks like Flutter and React Native is a valuable skill. These frameworks allow you to build mobile applications for both iOS and Android using a single codebase.
9. Security Best Practices:
Cybersecurity is a growing concern, and full-stack developers need to be well-versed in security best practices. This includes knowledge of secure coding, data encryption, and protecting against common vulnerabilities like SQL injection and cross-site scripting (XSS).
10. Cloud Services:
Familiarity with cloud platforms such as AWS, Azure, and Google Cloud is essential. Full-stack developers should know how to leverage these platforms for hosting, scaling, and managing their applications.
11. Soft Skills:
Effective communication, problem-solving, and collaboration are essential soft skills for a full-stack developer. Working in multidisciplinary teams, understanding business requirements, and providing solutions are equally important alongside technical skills.

To become a full-stack developer, I highly recommend ACTE Technologies. ACTE Technologies is a trusted provider of IT training and certification programs, including specialized full-stack developer training with career guidance. Whether you're aiming to boost your career or dive into the world of development, ACTE Technologies can be your partner on the path to full-stack developer training expertise.
Thank you!
0 notes
Text
Comparison of NativeScript and React Native frameworks with code examples
Both NativeScript and React Native are popular frameworks for building cross-platform mobile applications. They enable developers to use JavaScript and Native UI components to create apps that run on both iOS and Android platforms. Below is a comparison of the two frameworks along with some code examples to illustrate their usage.
Language:
NativeScript: NativeScript supports JavaScript, TypeScript, and Angular for building apps. You can also use Vue.js with NativeScript Vue.
React Native: React Native primarily uses JavaScript (ES6+), but you can also use TypeScript with it.
UI Components:
NativeScript: It provides access to native UI components through a single JavaScript API, allowing you to create UI elements using XML, CSS, and JavaScript.
React Native: React Native components are built using React components, which are then translated to native UI components on each platform.
Code Examples:
// main-page.js const { Observable } = require("tns-core-modules/data/observable"); const { Label } = require("tns-core-modules/ui/label");
function onNavigatingTo(args) { const page = args.object; const vm = new Observable(); vm.set("message", "Hello, NativeScript!"); page.bindingContext = vm;const label = new Label(); label.text = "Dynamic Label"; page.content = label;
}
exports.onNavigatingTo = onNavigatingTo;
// App.js import React, { useState } from 'react'; import { View, Text } from 'react-native';
const App = () => { const [message, setMessage] = useState('Hello, React Native!'); return ( {message} ); };
export default App;
Community and Ecosystem:
React Native has a larger community and ecosystem due to its earlier release and the popularity of React. This means more libraries, tools, and resources are available.
NativeScript has a growing community and ecosystem, but it might not be as extensive as React Native's.
Performance:
NativeScript claims to provide native-like performance, as it directly uses native UI components, but it may vary depending on the complexity of the app and the platform.
React Native's performance is generally good, but it might have some overhead due to the bridge that connects JavaScript and native components.
Learning Curve:
React Native might have a shorter learning curve for developers already familiar with React, as they can reuse their knowledge of React components.
NativeScript might be more straightforward for developers familiar with JavaScript and XML-based UI.
Both frameworks have their strengths and can be suitable for different projects. The choice between them depends on factors like the existing skill set of your team, specific project requirements, and the preference for the development approach.
Remember, code examples are simplified for demonstration purposes. Real-world projects would require more complexity and organization, such as using state management, handling navigation, and integrating with APIs.
1 note
·
View note
Photo

VueFire: CRUD Application with Vue.js and Firebase VueFire: CRUD Application with Vue.js and Firebase Want to learn how to integrate Firebase and Vuefire into your Vue.js applications? This video does just that ... source
#application#crud#firebase#vue crud#vue crud firebase#vue fire#vue firebase crud#vue firebase example#vue firebase tutorial#vue tutorial hello world#vue.js firebase#vue.js vuefire#vuefire#vuefire tutorial#vuefire vuejs#VueFire: CRUD Application with Vue.js and Firebase#vuejs#vuejs firebase#vuejs firebase tutorial
0 notes
Text
Hire Vuejs Developer
Hire Vuejs developer with a proven track record to power your digital transformation. Our Vue js developers have deep knowledge and extensive experience in empowering businesses with the most advanced Agile software development tools, strategies, and methodologies.
Vue.js is our main front-end development technology and we have gained world-class experience building world-class single-page Vue.js web applications.
Contact Us Now
ByteCipher Pvt. Ltd.
+17472129362
0 notes
Text
JavaScript is a high-level, dynamic, untyped, and interpreted programming language. It has been standardized in the ECMAScript language specification. Alongside HTML and CSS, it is one of the three essential technologies of World Wide Web content production; the majority of websites employ it and it is supported by all modern web browsers without plug-ins or any kind of other extensions.
Q 1. Is JavaScript and JScript the same?
Answer. Both JavaScript vs JScript is designed to make dynamic web pages and interactive content.
Javascript is a scripting language (supports scripts) for Web pages but it is also used in non-browser environments as well. It is a powerful, lightweight, interpreted, scripting language with first-class functions (i.e. the language supports passing functions as arguments to other functions).
JScript is also a scripting language, much similar to JavaScript. It is a dialect of the popular ECMAScript standard reverse-engineered by Microsoft. JScript is subsidy by Microsoft and used in one of the most popular web browsers Microsoft’s Internet Explorer. JScript can also be called “Microsoft’s JavaScript”.
Q 2. Justify the use of let and const in JavaScript?
Answer. Earlier in javascript, developers use the var keyword for creating variables. let & const keyword is introduced in version ES6 with the vision of creating two different types of variables in javascript one is immutable and the other is mutable. The use if let and const in JavaScript:
let
let is used for variable declaration as it comes as an improvement to the var declarations. let is a block code bounded as {}. So a variable declared in a block with the let is only available for use within that block.
Example:
let greeting = "say Hi";
let times = 4;
if (times > 3) {
let hello = "say Hello instead";
console.log(hello);//"say Hello instead"
}
console.log(hello) // hello is not defined
const
Variables declared with the const maintain constant values. const declarations share some similarities with let declarations.
Like let declarations, const declarations can only be accessed within the block it was declared in.
const cannot be updated or re-declared
This means that the value of a variable declared with const remains the same within its scope. It cannot be updated or re-declared. So if we declare a variable with const.
Example:
const greeting = "say Hi";
greeting = "say Hello instead";//error : Assignment to constant variable.
Q 3. Explain the MUL function in JavaScript?
Answer. MUL means a simple multiplication of numbers. It is a technique in which you pass one value as an argument in a function and that function returns another function to which you pass the second value and the process goes on. Multiplies two expressions. This is the functional equivalent of the (*) operator.
Q 4. List the Frameworks and Data types supported by JavaScript?
Answer. The frameworks used by JavaScript are:
Node.js
Angular.js
React
Vue.js
Ember.js
Meteor
Backbone.js
Data types supported by JavaScript are:
Symbol
String
Boolean
Null
Undefined
Number
Object
Q 5. How you can redirect a page to another page in JavaScript?
Answer. There are several ways to redirect the page to another page in JavaScript. These are:
Using location.href: It is the first approach to redirect page. In this, we can go back to access the original document.
Using location.replace: Another approach to redirect page. In this, it is not possible to navigate back to the original document by clicking on the back button as it r
0 notes
Text
Hello Errors: The Future-Forward Website Development Company in Bangalore

In the modern digital economy, having a high-performing website is no longer optional—it's essential. For businesses seeking to make a lasting impression, a website is the face of their brand, the first point of contact, and a powerful tool for conversion. And when you're looking to build that digital foundation in India’s Silicon Valley, choosing the right website development company in Bangalore becomes the game-changer.
Welcome to Hello Errors—your trusted technology partner for building immersive, dynamic, and scalable web solutions. Positioned at the intersection of innovation and impact, Hello Errors delivers more than websites—we craft digital experiences that perform, engage, and convert.
Why Your Business Needs a High-Performance Website
Before diving into what makes Hello Errors stand out as a top website development company in Bangalore, let’s understand why your business needs a stellar website:
First Impressions Count: Your website is the digital storefront of your brand. A slow, outdated, or unattractive site turns away potential customers.
SEO & Visibility: A well-developed website ranks higher on search engines, making it easier for customers to find you online.
Customer Engagement: Interactive elements, clear navigation, and responsive design enhance user experience and engagement.
Conversions & Sales: Every element—from loading speed to layout—contributes to turning visitors into leads or customers.
In short, your website is your most powerful marketing asset—and Hello Errors ensures it delivers on that promise.
Bangalore: The Digital Innovation Hub of India
Why is it ideal to partner with a website development company in Bangalore?
Bangalore is not just India’s tech capital; it’s the epicenter of digital transformation. With a vibrant ecosystem of startups, IT giants, and creative agencies, Bangalore is where technology meets talent. Businesses here are early adopters of innovation and demand world-class web development standards.
By choosing a local company like Hello Errors, you benefit from:
On-ground support and collaboration
Access to top-tier developers and designers
A deep understanding of both local and global digital trends
Faster turnaround and time zone alignment
Hello Errors: More Than Just Code
At Hello Errors, we believe in crafting websites that reflect your brand ethos and deliver business outcomes. As a next-gen website development company in Bangalore, we focus on five key pillars:
1. Human-Centered Design
Our process begins with your user. Through deep research and UX strategy, we build intuitive interfaces that reduce friction and increase engagement. Whether you’re in retail, healthcare, education, or B2B services, our UI/UX approach adapts to your audience’s behavior.
2. Technology-Driven Development
We don’t follow trends—we set them. Our developers are well-versed in the latest frameworks and languages, such as:
ReactJS, Vue.js, Angular (Frontend)
Node.js, Python, PHP (Backend)
WordPress, Shopify, and JAMstack (CMS and static site solutions)
APIs and microservices architecture for scalable projects
3. Mobile-First Philosophy
With the majority of users browsing from their smartphones, our websites are designed mobile-first and tested across devices. Responsive design is a given; seamless mobile performance is a priority.
4. SEO from the Ground Up
What good is a great website if no one finds it? Unlike many developers, Hello Errors integrates SEO best practices into the development process—from clean code to fast load speeds, schema markups, and mobile responsiveness.
5. Security and Scalability
Security is not an afterthought—it’s baked into every line of code we write. We use the best practices in authentication, data protection, and secure hosting. Our sites are built to scale with your growing business.
Our Holistic Digital Services
While we are known as a premium website development company in Bangalore, Hello Errors is also a full-service digital partner offering:
✅ Web Development
From static business sites to advanced portals and ecommerce platforms—we design and develop sites that captivate and convert.
✅ Mobile App Development
We create cross-platform and native apps that combine sleek UI with robust functionality.
✅ SEO & Digital Marketing
Improve your rankings, drive more organic traffic, and grow your digital presence with our SEO and content marketing services.
✅ Artificial Intelligence & ML Integration
We help businesses innovate with smart features like chatbots, predictive analytics, and personalized recommendations.
✅ UI/UX Design
From wireframes to interactive prototypes, we design fluid experiences that keep users coming back.
What Makes Hello Errors Unique?
We don’t just compete—we differentiate. Here’s what sets Hello Errors apart from any other website development company in Bangalore:
Consultative Approach: We listen before we code. Every project starts with strategy, not assumptions.
Results-Driven Delivery: We measure success in traffic, engagement, and conversions—not just aesthetics.
Ongoing Support & Maintenance: Post-launch, we don’t disappear. We optimize, update, and scale as your business evolves.
Agility & Speed: Quick turnaround doesn’t mean compromise. With agile development, we deliver MVPs faster—without sacrificing quality.
Transparent Pricing: No hidden fees. No confusing jargon. Just clear deliverables at fair prices.
Use Case: Boosting a Startup’s Digital Footprint
Let’s consider a real-world example:
A local startup selling organic food online approached Hello Errors to improve their digital reach. They had a basic website with poor traffic and weak conversions. Within 60 days, Hello Errors transformed their online presence by:
Redesigning their website with fresh UI/UX
Integrating a seamless shopping cart and checkout flow
Implementing technical SEO and keyword strategy
Adding a chatbot powered by AI for real-time customer queries
Result? A 3x increase in organic traffic and a 2.5x increase in sales within 90 days.
Ready to Transform Your Website?
If you’re a business owner, entrepreneur, or startup looking to launch or upgrade your digital presence, there’s no better time to act. The digital landscape is evolving fast—and your website must be up to speed.
Choosing the right website development company in Bangalore can be the difference between digital stagnation and exponential growth.
Let’s Build Something Amazing Together
At Hello Errors, we turn ideas into interactive realities. With unmatched expertise, creativity, and a customer-first mindset, we are your trusted web development partner in Bangalore.
Get in touch today for a free consultation or visit our portfolio at https://helloerrors.in to see how we’ve helped brands like yours grow digitally.
#WebsiteDevelopmentCompanyInBangalore#HelloErrors#WebDesignBangalore#DigitalTransformation#UIDesign#BangaloreTech#BusinessGrowth#SEOCompanyBangalore#AppDevelopmentIndia#AIWebSolutions
0 notes
Text
Simplify Static Asset Management With Vue.js Single-File Component

Static asset management is one of the more painful and mysterious challenges front-end developers face. We want our source code to be simple to develop and maintain, but we rely on browsers to be lean and mean. Browsers can’t be expected to understand our fancy source files with conveniences like Sass or the newest bleeding edge JavaScript features. We configure transpilers, linters, and compressors that watch for source code changes or get triggered by build processes. And finally, these tools emit static assets that a browser can interpret

Even when we don’t use fancy preprocessors, we still copy the source files to a dist directory to deploy them…because…well…it’s just what we do!

On top of this complexity, we have traditionally maintained a separation of concerns between markup, scripting, and styling. This separation can lead to extreme bloat that makes our applications difficult to maintain.
Imagine a request to remove a component from a view. You remove the markup…but can you track down CSS selectors that are specific to this component? All the media queries? Do you feel safe removing code that may affect other parts of the view? What about a request to modify a component’s appearance? Do you add a new class to your updated component and leave the old styling behind, just in case there are other parts of the view that are styled by it? Technical debt accumulates. Eventually, you have a pile of dead code mixed in with the good stuff. It’s very difficult to clean up, and nobody wants to pay for the effort.

Not to imply that your code is inherently bad. It’s a consequence of the separation of concerns that has made the internet look sharp since the W3C adopted CSS in 1996.
So, what are our alternatives? Inline CSS? An occasional inline style attribute is acceptable in the 21st century. But even with CSS-in-JS libraries, this solution can be challenging to scale. We need the cascade. We need media queries.
Many modern frameworks combine JavaScript with markup; it’s the core of the React, Angular, and Vue.js revolution. The concept of “styled components” is also trending. But unification usually comes at a cost. The learning curve, awkward code structure, and dependency on 3rd party libraries may outweigh the advantages. However, Vue’s out-of-the-box support for the concept makes it simple to grasp and implement.

The Vue.js framework Single-File Component (SFC) allows you to combine templating, scripting, and styling in a single source file that can accept props and manage state. Vue CLI — the “beginner” installation of Vue.js — will pre-configure the bridge between your .vue source files and webpack that requires absolutely no configuration or webpack knowledge. Let’s open a terminal and quickly build a working example using npm.
1.Install Vue CLI: npm install -g @vue/cli
2.Create a new project (accept the default settings): vue create vue-sfc-example
3.Start the project: npm run serve
4. Render HelloWorld.vue in a browser: http://localhost:8080

SO easy. Let’s open the source to see what we built.
<template>
<div class="hello">
...some markup...
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
The <template> tag wraps Vue template syntax enhanced markup.
The <script> tag wraps JavaScript.
The <style> tag wraps CSS.
Aside from placing the styling at the end of the file, this source file looks an awful lot like an html file that a browser could interpret. There is a lot going on under the hood, but Vue doesn’t clutter the source with tooling bloat.
Let’s concentrate on the <style> tag. The boilerplate contains some basic CSS, and an attribute named “scoped”. As the code comment implies, this attribute allows you to “scope” this block to only apply to this particular component, by automatically namespacing the CSS. Compare this to a more traditional approach, which might involve creating a selector like: “#hello-world-component-namespace.this-component {...}” in some faraway css file. The scoped attribute is optional. If you want to modify child components, one approach is to exclude the scoped attribute. You may also use multiple blocks of CSS, in case you wish to scope part of the code, but style children with a separate CSS block.
<style scoped>
h3 {
margin: 40px 0 0;
}
...
</style>
<style>
#child-component > h3 {
margin: 10px;
}
...
</style>
If you inspect the source code in your browser, you can see this style block rendered in the head of the document:
<style type="text/css">h3[data-v-469af010] {
margin: 40px 0 0;
}
ul[data-v-469af010] {
list-style-type: none;
padding: 0;
}
li[data-v-469af010] {
display: inline-block;
margin: 0 10px;
}
a[data-v-469af010] {
color: #42b983;
}
</style>
There is no need to version or deploy a CSS file, in this example. The data attribute in the first block is no accident. It uniquely identifies the component this styling is scoped to.
<div data-v-469af010="" class="hello">...</div>
Predictably, namespacing is suppressed for code blocks that are not scoped.
<style type="text/css">
#child-component > h3 {
margin: 10px;
}
</style>
An alternative to this approach is the ::v-deep combinator, which allows you to style children from a scoped block. Details can be found here.
But what about my Sass? Good news: SFCs tap into all of your favorite webpack preprocessors. Install sass-loader with npm:
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
> li {
display: inline-block;
margin: 0 10px;
a {
color: #42b983;
&.very-green {
#00ff00;
}
}
}
}
</style>
But what about my Sass globals, includes, mixins, etc.? Never fear — the Sass block you include in your SFCs works just like your typical Sass source file. You can pass includes, set variables, nest media queries, and any other Sass convenience.
<style scoped lang="scss">
@import "mixins";
@import "global/global";
#main {
padding-top: em(54);
@media (min-width: $screen-md) {
padding-top: 0;
}
}
</style>
The vue-loader, which is included and pre-configured by Vue CLI, makes all of this work. Sass/Scss, Less, Babel, TypeScript, and other popular preprocessors and linters are supported. These features can be discretely configured, to the delight of advanced users.
The Vue.js SFC offers the convenience our source code deserves, without the file management and webpack tooling headaches. You can also use the component state to set class and style inside your templates, using built-in lifecycle hooks. It is also important to note that you can still include CSS the typical way, or in a mixed mode. This is especially handy when using rapid prototyping libraries like Bootstrap.
What’s the catch? Vue.js is a relatively new player. It’s picking up steam, but there aren’t as many applications using the framework as the competing products — Angular and React. That means the user community is comparably small. Examples are slim and basic. You are cutting your own trail. Also, we have detected some “spookiness” in the way preprocessors react to code structure. The preprocessors may need some configuration and babysitting, once you scale into a larger project.
_________________________________________
0 notes
Photo

How to Build a Chrome Extension with Vue
Browser extensions are small programs that can modify and enhance the functionality of a web browser. They can be used for a variety of tasks, such as blocking ads, managing passwords, organizing tabs, altering the look and behavior of web pages, and much more.
The good news is that browser extensions aren’t difficult to write. They can be created using the web technologies you’re already familiar with — HTML, CSS and JavaScript — just like a regular web page. However, unlike regular web pages, extensions have access to a number of browser-specific APIs, and this is where the fun begins.
In this tutorial, I’m going to show you how to build a simple extension for Chrome, which alters the behavior of the new tab page. For the JavaScript part of the extension, I’ll be using the Vue.js framework, as it will allow us to get up and running quickly and is a lot of fun to work with.
The code for this tutorial can be found on GitHub.
The Basics of a Chrome Extension
The core part of any Chrome extension is a manifest file and a background script. The manifest file is in a JSON format and provides important information about an extension, such as its version, resources, or the permissions it requires. A background script allows the extension to react to specific browser events, such as the creation of a new tab.
To demonstrate these concepts, let’s start by writing a “Hello, World!” Chrome extension.
Make a new folder called hello-world-chrome and two files: manifest.json and background.js:
mkdir hello-world-chrome cd hello-world-chrome touch manifest.json background.js
Open up manifest.json and add the following code:
{ "name": "Hello World Extension", "version": "0.0.1", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false } }
The name, version and manifest_version are all required fields. The name and version fields can be whatever you want; the manifest version should be set to 2 (as of Chrome 18).
The background key allows us to register a background script, listed in an array after the scripts key. The persistent key should be set to false unless the extension uses chrome.webRequest API to block or modify network requests.
Now let’s add the following code to background.js to make the browser say hello when the extension is installed:
chrome.runtime.onInstalled.addListener(() => { alert('Hello, World!'); });
Finally, let’s install the extension. Open Chrome and enter chrome://extensions/ in the address bar. You should see a page displaying the extensions you’ve installed.
As we want to install our extension from a file (and not the Chrome Web Store) we need to activate Developer mode using the toggle in the top right-hand corner of the page. This should add an extra menu bar with the option Load unpacked. Click this button and select the hello-world-chrome folder you created previously. Click Open and you should see the extension installed and a “Hello, World!” popup appear.

Congratulations! You just made a Chrome extension.
Overriding Chrome’s New Tab Page
The next step will to have our extension greet us when we open up a new tab. We can do this by making use of the Override Pages API.
Note: before you progress, please make sure to disable any other extensions which override Chrome’s new tab page. Only one extension at a time may alter this behavior.
We’ll start off by creating a page to display instead of the new tab page. Let’s call it tab.html. This should reside in the same folder as your manifest file and background script:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My New Tab Page!</title> </head> <body> <h1>My New Tab Page!</h1> <p>You can put any content here you like</p> </body> </html>
Next we need to tell the extension about this page. We can do so by specifying a chrome_url_overrides key in our manifest file, like so:
"chrome_url_overrides": { "newtab": "tab.html" }
Finally, you need to reload the extension for the changes to take effect. You can do this by clicking the reload icon for the Hello World extension on Chrome’s extensions page.

Now, when you open a new tab, you should be greeted by your custom message.
Adding Vue to the Extension
Now we have a very basic implementation of our extension up and running, the time has come to think about what the rest of the desired functionality will look like. When a user opens a new tab, I would like the extension to:
Fetch a joke from the wonderful icanhazdadjoke.com.
Display that joke in a nicely formatted manner to the user.
Display a button for the user to favorite the joke. This will save the joke to chrome.storage.
Display a button for the user to list favorited jokes.
You could, of course, do all of this with plain JavaScript, or a library like jQuery — and if that’s your thing, feel free!
For the purposes of this tutorial, however, I’m going to implement this functionality using Vue and the awesome vue-web-extension boilerplate.
Using Vue allows me to write better, more organized code faster. And as we’ll see, the boilerplate provides several scripts that take the pain out of some of the common tasks when building a Chrome extension (such as having to reload the extension whenever you make changes).
vue-web-extension-boilerplate
This section assumes that you have Node and npm installed on your computer. If this isn’t the case, you can either head to the project’s home page and grab the relevant binaries for your system, or you can use a version manager. I would recommend using a version manager.
We’ll also need Vue CLI installed and the @vue/cli-init package:
npm install -g @vue/cli npm install -g @vue/cli-init
With that done, let’s grab a copy of the boilerplate:
vue init kocal/vue-web-extension new-tab-page
This will open a wizard which asks you a bunch of questions. To keep this tutorial focused, I answered as follows:
? Project name new-tab-page ? Project description A Vue.js web extension ? Author James Hibbard <[email protected]> ? License MIT ? Use Mozilla's web-extension polyfill? No ? Provide an options page? No ? Install vue-router? No ? Install vuex? No ? Install axios? Yes ? Install ESLint? No ? Install Prettier? No ? Automatically install dependencies? npm
You can adapt your answers to suit your preferences, but the main thing to be certain of is that you choose to install axios. We’ll be using this to fetch the jokes.
Next, change into the project directory and install the dependencies:
cd new-tab-page npm install
And then we can build our new extension using one of the scripts the boilerplate provides:
npm run watch:dev
This will build the extension into a dist folder in the project root for development and watch for changes.
To add the extension to Chrome, go through the same process as outlined above, making sure to select the dist folder as the extension directory. If all goes according to plan, you should see a “Hello world!” message when the extension initializes.
Project Setup
Let’s take a minute to look around our new project and see what the boilerplate has given us. The current folder structure should look like this:
. ├── dist │ └── <the built extension> ├── node_modules │ └── <one or two files and folders> ├── package.json ├── package-lock.json ├── scripts │ ├── build-zip.js │ └── remove-evals.js ├── src │ ├── background.js │ ├── icons │ │ ├── icon_128.png │ │ ├── icon_48.png │ │ └── icon.xcf │ ├── manifest.json │ └── popup │ ├── App.vue │ ├── popup.html │ └── popup.js └── webpack.config.js
As you can see, from the config file in the project root, the boilerplate is using webpack under the hood. This is awesome, as this gives us Hot Module Reloading for our background script.
The src folder contains all of the files we’ll be using for the extension. The manifest file and background.js should be familiar, but also notice a popup folder containing a Vue component. When the boilerplate builds the extension into the dist folder, it will pipe any .vue files through the vue-loader and output a JavaScript bundle which the browser can understand.
Also in the src folder is an icons folder. If you look in Chrome’s toolbar, you should see a new icon for our extension (also known as the browser action). This is being pulled from this folder. If you click it, you should see a popup open which displays “Hello world!” This is created by popup/App.vue.
Finally, note a scripts folder containing two scripts — one to remove eval usages to comply with the Content Security Policy of Chrome Web Store and one to package your extension into a .zip file, which is necessary when uploading it to the Chrome Web Store.
There are also various scripts declared in the package.json file. We’ll be using npm run watch:dev for developing the extension and later on npm run build-zip to generate a ZIP file to upload to the Chrome Web Store.
The post How to Build a Chrome Extension with Vue appeared first on SitePoint.
by James Hibbard via SitePoint http://bit.ly/2HN1fjr
0 notes
Text
Using Vue.js To Create An Interactive Weather Dashboard With APIs
Using Vue.js To Create An Interactive Weather Dashboard With APIs
Souvik Sarkar
2019-02-01T13:00:18+01:002019-02-01T11:48:39+00:00
(This is a sponsored article.) In this tutorial, you will build a simple weather dashboard from scratch. It will be a client-end application that is neither a “Hello World” example, nor too intimidating in its size and complexity.
The entire project will be developed using tools from the Node.js + npm ecosystem. In particular, we will be heavily relying on the Dark Sky API for the data, Vue.js for all the heavy lifting, and FusionCharts for data visualization.
Prerequisites
We expect that you are familiar with the following:
HTML5 and CSS3 (we will also be using the basic features provided by Bootstrap;
JavaScript (especially ES6 way of using the language);
Node.js and npm (the basics of the environment and package management is just fine).
Apart from the ones mentioned above, it would be great if you have familiarity with Vue.js, or any other similar JavaScript framework. We don’t expect you to know about FusionCharts — it’s so easy to use that you will learn it on the fly!
Expected Learnings
Your key learnings from this project will be:
How to plan about implementing a good dashboard
How to develop applications with Vue.js
How to create data-driven applications
How to visualize data using FusionCharts
In particular, each of the sections take you a step closer to the learning goals:
An Introduction To The Weather Dashboard This chapter gives you an overview of different aspects of the undertaking.
Create The Project In this section, you learn about creating a project from scratch using the Vue command-line tool.
Customize The Default Project Structure The default project scaffolding that you get in the previous section is not enough; here you learn the additional stuff needed for the project from a structural point of view.
Data Acquisition And Processing This section is the meat of the project; all the critical code for acquiring and processing data from the API is showcased here. Expect to spend maximum time on this section.
Data Visualization With FusionCharts Once we have all the data and other moving parts of the project stabilized, this section is dedicated towards visualizing the data using FusionCharts and a bit of CSS.
1. The Dashboard Workflow
Before we dive into the implementation, it is important to be clear about our plan. We break our plan into four distinct aspects:
Requirements
What are our requirements for this project? In other words, what are the things that we want to showcase through our Weather Dashboard? Keeping in mind that our intended audience are probably mere mortals with simple tastes, we would like to show them the following:
Details of the location for which they want to see the weather, along with some primary information about the weather. Since there are no stringent requirements, we will figure out the boring details later. However, at this stage, it is important to note that we will have to provide the audience a search box, so that they can provide input for the location of their interest.
Graphical information about the weather of their location of interest, such as:
Temperature variation for the day of query
Highlights of today’s weather:
Wind Speed and Direction
Visibility
UV Index
Note: The data obtained from the API provides information regarding many other aspects of the weather. We choose not to use all of them for the sake of keeping the code to a minimum.
Structure
Based on the requirements, we can structure our dashboard as shown below:
(Large preview)
Data
Our dashboard is as good as the data we get, because there will be no pretty visualizations without proper data. There are plenty of public APIs that provide weather data — some of them are free, and some are not. For our project, we will collect data from the Dark Sky API. However, we will not be able to poll the API endpoint from the client end directly. Don’t worry, we have a workaround that will be revealed just at the right time! Once we get the data for the searched location, we will do some data processing and formatting — you know, the type of technicalities that helps us pay the bills.
Visualization
Once we get clean and formatted data, we plug it in to FusionCharts. There are very few JavaScript libraries in the world as capable as FusionCharts. Out of the vast number of offerings from FusionCharts, we will use only a few — all written in JavaScript, but works seamlessly when integrated with the Vue wrapper for FusionCharts.
Armed with the bigger picture, let’s get our hands dirty — it’s time to make things concrete! In the next section, you will create the basic Vue project, on top of which we will build further.
2. Creating The Project
To create the project, execute the following steps:
Install Node.js + npm (If you have Node.js installed on your computer, skip this step.) Node.js comes with npm bundled with it, so you don’t need to install npm separately. Depending on the operating system, download and install Node.js according to the instructions given here. Once installed, it’s probably a good idea to verify if the software is working correctly, and what are their versions. To test that, open the command-line/terminal and execute the following commands:
node --version npm --version
Install packages with npm Once you have npm up and running, execute the following command to install the basic packages necessary for our project.
npm install -g vue@2 vue-cli@2
Initialize project scaffolding with vue-cli Assuming that the previous step has gone all well, the next step is to use the vue-cli — a command-line tool from Vue.js, to initialize the project. To do that, execute the following:
Initialize the scaffolding with webpack-simple template.
vue init webpack-simple vue_weather_dashboard
You will be asked a bunch of questions — accepting the defaults for all but the last question will be good enough for this project; answer N for the last one.
(Large preview)
Keep in mind that although webpack-simple is excellent for quick prototyping and light application like ours, it is not particularly suited for serious applications or production deployment. If you want to use any other template (although we would advise against it if you are a newbie), or would like to name your project something else, the syntax is:
vue init [template-name] [project-name]
Navigate to the directory created by vue-cli for the project.
cd vue_weather_dashboard
Install all the packages mentioned in the package.json, which has been created by the vue-cli tool for the webpack-simple template.
npm install
Start the development server and see your default Vue project working in the browser!
npm run dev
If you are new to Vue.js, take a moment to savor your latest achievement — you have created a small Vue application and its running at localhost:8080!
(Large preview)
Brief Explanation Of The Default Project Structure
It’s time to take a look at the structure inside the directory vue_weather_dashboard, so that you have an understanding of the basics before we start modifying it.
The structure looks something like this:
vue_weather_dashboard |--- README.md |--- node_modules/ | |--- ... | |--- ... | |--- [many npm packages we installed] | |--- ... | |--- ... |--- package.json |--- package-lock.json |--- webpack.config.js |--- index.html |--- src | |--- App.vue | |--- assets | | |--- logo.png | |--- main.js
Although it might be tempting to skip getting familiar with the default files and directories, if you are new to Vue, we strongly recommend at least taking a look at the contents of the files. It can be a good educational session and trigger questions that you should pursue on your own, especially the following files:
package.json, and just a glance at its cousin package-lock.json
webpack.config.js
index.html
src/main.js
src/App.vue
A brief explanation of each of the files and directories shown in the tree diagram are given below:
README.md No prize for guessing — it is primarily for humans to read and understand the steps necessary for creating the project scaffolding.
node_modules/ This is the directory where npm downloads the packages necessary for kickstarting the project. The information about the packages necessary are available in the package.json file.
package.json This file is created by the vue-cli tool based on the requirements of the webpack-simple template, and contains information about the npm packages (including with their versions and other details) that must be installed. Take a hard look at the content of this file — this is where you should visit and perhaps edit to add/delete packages necessary for the project, and then run npm install. Read more about package.json here.
package-lock.json This file is created by npm itself, and is primarily meant for keeping a log of things that npm downloaded and installed.
webpack.config.js This a JavaScript file that contains the configuration of webpack — a tool that bundles different aspects of our project together (code, static assets, configuration, environments, mode of use, etc.), and minifies before serving it to the user. The benefit is that all things are tied together automatically, and the user experience enhances greatly because of the improvement in the application’s performance (pages are served quickly and loads faster on the browser). As you might encounter later, this is the file that needs to be inspected when something in the build system does not works the way it is intended to be. Also, when you want to deploy the application, this is one of the key files that needs to be edited (read more here).
index.html This HTML file serves as the matrix (or you can say, template) where data and code is to be embedded dynamically (that’s what Vue primarily does), and then served to the user.
src/main.js This JavaScript file contains code that primarily manages top/project level dependencies, and defines the topmost level Vue component. In short, it orchestrates the JavaScript for the entire project, and serves as the entry point of the application. Edit this file when you need to declare project-wide dependencies on certain node modules, or you want something to be changed about the topmost Vue component in the project.
src/App.vue In the previous point, when we were talking about the “topmost Vue component”, we were essentially talking about this file. Each .vue file in the project is a component, and components are hierarchically related. At the start, we have only one .vue file, i.e. App.vue, as our only component. But shortly we will add more components to our project (primarily following the structure of the dashboard), and link them in accordance to our desired hierarchy, with App.vue being the ancestor of all. These .vue files will contain code in a format that Vue wants us to write. Don’t worry, they are JavaScript code written maintaining a structure that can keep us sane and organized. You have been warned — by the end of this project, if you are new to Vue, you may get addicted to the template — script — style way of organizing code!
Now that we have created the foundation, it’s time to:
Modify the templates and tweak the configuration files a bit, so that the project behaves just the way we want.
Create new .vue files, and implement the dashboard structure with Vue code.
We will learn them in the next section, which is going to be a bit long and demands some attention. If you need caffeine or water, or want to discharge — now is the time!
3. Customizing The Default Project Structure
It’s time to tinker with the foundation that the scaffolded project has given us. Before you start, ensure that the development server provided by webpack is running. The advantage of running this server continuously is that any changes you make in the source code — one you save it and refresh the web page — it gets immediately reflected on the browser.
If you want to start the development server, just execute the following command from the terminal (assuming your current directory is the project directory):
npm run dev
In the following sections, we will modify some of the existing files, and add some new files. It will be followed by brief explanations of the content of those files, so that you have an idea of what those changes are meant to do.
Modify Existing Files
index.html
Our application is literally a single page application, because there is just one webpage that gets displayed on the browser. We will talk about this later, but first let’s just make our first change — altering the text within the <title> tag.
With this small revision, the HTML file looks like the following:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <!-- Modify the text of the title tag below --> <title>Vue Weather Dashboard</title> </head> <body> <div id="app"></div> <script src="/dist/build.js"></script> </body> </html>
Take a moment to refresh the webpage at localhost:8080, and see the change reflected on the title bar of the tab on the browser — it should say “Vue Weather Dashboard”. However, this was just to demonstrate you the process of making changes and verifying if it’s working. We have more things to do!
This simple HTML page lacks many things that we want in our project, especially the following:
Some meta information
CDN links to Bootstrap (CSS framework)
link to custom stylesheet (yet to be added in the project)
Pointers to the Google Maps Geolocation API from <script> tag
After adding those things, the final index.html has the following content:
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="src/css/style.css"> <title>Weather Dashboard</title> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-lCjpg1xbw-nsCc11Si8Ldg2LKYizqI4&libraries=places"></script> </head> <body> <div id="app"></div> <script src="/dist/build.js"></script> </body> </html>
Save the file, and refresh the webpage. You might have noticed a slight bump while the page was getting loaded — it is primarily due to the fact that the page style is now being controlled by Bootstrap, and the style elements like fonts, spacing, etc. are different from the default we had earlier (if you are not sure, roll back to the default and see the difference).
(Large preview)
Note: One important thing before we move on — the URL for the Google Maps API contains a key which is a property of FusionCharts. For now, you can use this key to build the project, as we don’t want you to get bogged down by these type of minute details (which can be distractions while you are new). However, we strongly urge you to generate and use your own Google Maps API key once you have made some progress and feel comfortable to pay attention to these tiny details.
package.json
At the time of writing this, we used certain versions of the npm packages for our project, and we know for sure that those things work together. However, by the time you are executing the project, it is very much possible that the latest stable versions of the packages that npm downloads for you are not the same as we used, and this might break the code (or do things that are beyond our control). Thus, it is very important to have the exact same package.json file that was used to build this project, so that our code/explanations and the results you get are consistent.
The content of the package.json file should be:
{ "name": "vue_weather_dashboard", "description": "A Vue.js project", "version": "1.0.0", "author": "FusionCharts", "license": "MIT", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "axios": "^0.18.0", "babel": "^6.23.0", "babel-cli": "^6.26.0", "babel-polyfill": "^6.26.0", "fusioncharts": "^3.13.3", "moment": "^2.22.2", "moment-timezone": "^0.5.21", "vue": "^2.5.11", "vue-fusioncharts": "^2.0.4" }, "browserslist": [ "> 1%", "last 2 versions", "not ie
We encourage you to go through the new package.json, and figure out what are functions of different objects in the json. You may prefer changing the value of the “author” key to your name. Also, the packages mentioned in the dependencies will reveal themselves at the right time in the code. For the time being, it’s sufficient to know that:
babel-related packages are for properly handling the ES6 style code by the browser;
axios deals with Promise-based HTTP requests;
moment and moment-timezone are for date/time manipulation;
fusioncharts and vue-fusioncharts are responsible for rendering charts:
vue, for obvious reasons.
webpack.config.js
As with package.json, we suggest you to maintain a webpack.config.js file that is consistent with the one we used for building the project. However, before making any changes, we recommend you to carefully compare the default code in the webpack.config.js, and the code we have provided below. You will notice quite a few differences — google them and have a basic idea of what they mean. Since explaining webpack configurations in depth is out of the scope of this article, you are on your own in this regard.
The customized webpack.config.js file is as follows:
var path = require('path') var webpack = require('webpack') module.exports = { entry: ['babel-polyfill', './src/main.js'], output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, module: { rules: [ { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ], }, { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { } // other vue-loader options go here } }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } } ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['*', '.js', '.vue', '.json'] }, devServer: { historyApiFallback: true, noInfo: true, overlay: true, host: '0.0.0.0', port: 8080 }, performance: { hints: false }, devtool: '#eval-source-map' } if (process.env.NODE_ENV === 'production') { module.exports.devtool = '#source-map' // http://vue-loader.vuejs.org/en/workflow/production.html module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }) ]) }
With changes made to the project’s webpack.config.js, it’s imperative that you stop the development server which is running (Ctrl + C), and restart it with the following command executed from the project’s directory after installing all the packages mentioned in the package.json file:
npm install npm run dev
With this, the ordeal of tweaking the configurations and ensuring that the right packages are in place ends. However, this also marks the journey of modifying and writing code, which is a bit long but also very rewarding!
src/main.js
This file is the key to top-level orchestration of the project — it is here that we define:
What the top level dependencies are (where to get the most important npm packages necessary);
How to resolve the dependencies, along with instructions to Vue on using plugins/wrappers, if any;
A Vue instance that manages the topmost component in the project: src/App.vue (the nodal .vue file).
In line with our goals for the src/main.js file, the code should be:
// Import the dependencies and necessary modules import Vue from 'vue'; import App from './App.vue'; import FusionCharts from 'fusioncharts'; import Charts from 'fusioncharts/fusioncharts.charts'; import Widgets from 'fusioncharts/fusioncharts.widgets'; import PowerCharts from 'fusioncharts/fusioncharts.powercharts'; import FusionTheme from 'fusioncharts/themes/fusioncharts.theme.fusion'; import VueFusionCharts from 'vue-fusioncharts'; // Resolve the dependencies Charts(FusionCharts); PowerCharts(FusionCharts); Widgets(FusionCharts); FusionTheme(FusionCharts); // Globally register the components for project-wide use Vue.use(VueFusionCharts, FusionCharts); // Instantiate the Vue instance that controls the application new Vue({ el: '#app', render: h => h(App) })
src/App.vue
This is one of the most important files in the entire project, and represents the topmost component in the hierarchy — the entire application itself, as a whole. For our project, this component will do all the heavy lifting, which we will explore later. For now, we want to get rid of the default boilerplate, and put something of our own.
If you are new to Vue’s way of organizing code, it would be better to get an idea of the general structure within the .vue files. The .vue files comprises of three sections:
Template This is where the HTML template for the page is defined. Apart from the static HTML, this section also contains Vue’s way of embedding dynamic content, using the double curly braces .
Script JavaScript rules this section, and is responsible for generating dynamic content that goes and sits within the HTML template at appropriate places. This section is primarily an object that is exported, and consists of:
Data This is a function itself, and usually it returns some desired data encapsulated within a nice data structure.
Methods An object that consists of one or more functions/methods, each of which usually manipulates data in some way or the other, and also controls the dynamic content of the HTML template.
Computed Much like the method object discussed above with one important distinction — while all the functions within the method object are executed whenever any one of them is called, the functions within the computed object behaves much more sensibly, and executes if and only if it has been called.
Style This section is for CSS styling that applies to the HTML of the page (written within template) — put the good old CSS here to make your pages beautiful!
Keeping the above paradigm in mind, let’s minimally customize the code in App.vue:
<template> <div id="app"> <p>This component’s code is in </p> </div> </template> <script> export default { data() { return { filename: 'App.vue' } }, methods: { }, computed: { }, } </script> <style> </style>
Remember that the above code snippet is simply for testing out that App.vue is working with our own code in it. It will later go on through a lot of changes, but first save the file and refresh the page on the browser.
(Large preview)
At this point, it’s probably a good idea to get some help in tooling. Check out the Vue devtools for Chrome, and if you don’t have much problems in using Google Chrome as your default browser for development, install the tool and play around with it a bit. It will come in extremely handy for further development and debugging, when things becomes more complicated.
Additional Directories And Files
The next step would be to add additional files, so that the structure of our project becomes complete. We would add the following directories and files:
src/css/ — style.css
src/assets/ — calendar.svg — vlocation.svg — search.svg — winddirection.svg — windspeed.svg
src/components/ — Content.vue — Highlights.vue — TempVarChart.vue — UVIndex.vue — Visibility.vue — WindStatus.vue
Note: Save the hyperlinked .svg files in your project.
Create the directories and files mentioned above. The final project structure should like look (remember to delete folders and files from the default structure that are now unnecessary):
vue_weather_dashboard/ |--- README.md |--- node_modules/ | |--- ... | |--- ... | |--- [many npm packages we installed] | |--- ... | |--- ... |--- package.json |--- package-lock.json |--- webpack.config.js |--- index.html |--- src/ | |--- App.vue | |--- css/ | | |--- style.css | |--- assets/ | | |--- calendar.svg | | |--- location.svg | | |--- location.svg | | |--- winddirection.svg | | |--- windspeed.svg | |--- main.js | |--- components/ | | |--- Content.vue | | |--- Highlights.vue | | |--- TempVarChart.vue | | |--- UVIndex.vue | | |--- Visibility.vue | | |--- WindStatus.vue
There might be some other files, like .babelrc, .gitignore, .editorconfig, etc. in the project’s root folder. You may ignore them safely for now.
In the following section, we will add minimal content to the newly added files, and test whether they are properly working.
src/css/style.css
Although it will not be of much use immediately, copy the following code to the file:
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500"); :root { font-size: 62.5%; } body { font-family: Roboto; font-weight: 400; width: 100%; margin: 0; font-size: 1.6rem; } #sidebar { position: relative; display: flex; flex-direction: column; background-image: linear-gradient(-180deg, #80b6db 0%, #7da7e2 100%); } #search { text-align: center; height: 20vh; position: relative; } #location-input { height: 42px; width: 100%; opacity: 1; border: 0; border-radius: 2px; background-color: rgba(255, 255, 255, 0.2); margin-top: 16px; padding-left: 16px; color: #ffffff; font-size: 1.8rem; line-height: 21px; } #location-input:focus { outline: none; } ::placeholder { color: #FFFFFF; opacity: 0.6; } #current-weather { color: #ffffff; font-size: 8rem; line-height: 106px; position: relative; } #current-weather>span { color: #ffffff; font-size: 3.6rem; line-height: 42px; vertical-align: super; opacity: 0.8; top: 15px; position: absolute; } #weather-desc { font-size: 2.0rem; color: #ffffff; font-weight: 500; line-height: 24px; } #possibility { color: #ffffff; font-size: 16px; font-weight: 500; line-height: 19px; } #max-detail, #min-detail { color: #ffffff; font-size: 2.0rem; font-weight: 500; line-height: 24px; } #max-detail>i, #min-detail>i { font-style: normal; height: 13.27px; width: 16.5px; opacity: 0.4; } #max-detail>span, #min-detail>span { color: #ffffff; font-family: Roboto; font-size: 1.2rem; line-height: 10px; vertical-align: super; } #max-summary, #min-summary { opacity: 0.9; color: #ffffff; font-size: 1.4rem; line-height: 16px; margin-top: 2px; opacity: 0.7; } #search-btn { position: absolute; right: 0; top: 16px; padding: 2px; z-index: 999; height: 42px; width: 45px; background-color: rgba(255, 255, 255, 0.2); border: none; } #dashboard-content { text-align: center; height: 100vh; } #date-desc, #location-desc { color: #ffffff; font-size: 1.6rem; font-weight: 500; line-height: 19px; margin-bottom: 15px; } #date-desc>img { top: -3px; position: relative; margin-right: 10px; } #location-desc>img { top: -3px; position: relative; margin-left: 5px; margin-right: 15px; } #location-detail { opacity: 0.7; color: #ffffff; font-size: 1.4rem; line-height: 20px; margin-left: 35px; } .centered { position: fixed; top: 45%; left: 50%; transform: translate(-50%, -50%); } .max-desc { width: 80px; float: left; margin-right: 28px; } .temp-max-min { margin-top: 40px } #dashboard-content { background-color: #F7F7F7; } .custom-card { background-color: #FFFFFF !important; border: 0 !important; margin-top: 16px !important; margin-bottom: 20px !important; } .custom-content-card { background-color: #FFFFFF !important; border: 0 !important; margin-top: 16px !important; margin-bottom: 0px !important; } .header-card { height: 50vh; } .content-card { height: 43vh; } .card-divider { margin-top: 0; } .content-header { color: #8786A4; font-size: 1.4rem; line-height: 16px; font-weight: 500; padding: 15px 10px 5px 15px; } .highlights-item { min-height: 37vh; max-height: 38vh; background-color: #FFFFFF; } .card-heading { color: rgb(33, 34, 68); font-size: 1.8rem; font-weight: 500; line-height: 21px; text-align: center; } .card-sub-heading { color: #73748C; font-size: 1.6rem; line-height: 19px; } .card-value { color: #000000; font-size: 1.8rem; line-height: 21px; } span text { font-weight: 500 !important; } hr { padding-top: 1.5px; padding-bottom: 1px; margin-bottom: 0; margin-top: 0; line-height: 0.5px; } @media only screen and (min-width: 768px) { #sidebar { height: 100vh; } #info { position: fixed; bottom: 50px; width: 100%; padding-left: 15px; } .wrapper-right { margin-top: 80px; } } @media only screen and (min-width:1440px) { #sidebar { width: 350px; max-width: 350px; flex: auto; } #dashboard-content { width: calc(100% — 350px); max-width: calc(100% — 350px); flex: auto; } }
src/assets/
In this directory, download and save the .svg files mentioned below:
calendar.svg
location.svg
search.svg
winddirection.svg
windspeed.svg
src/components/Content.vue
This is what we call a dumb component — a placeholder, that is there just to maintain the hierarchy, and essentially passes on data to its child components.
Remember that there is no technical bar for writing all our code in the App.vue file, but we take the approach of splitting up the code by nesting the components for two reasons:
To write clean code, which aids readability and maintainability;
To replicate the same structure that we will see on screen, i.e., the hierarchy.
Before we nest the component defined in Content.vue within the root component App.vue, let’s write some toy (but educational) code for Content.vue:
<template> <div> <p>This child components of Content.vue are:</p> <ul> <li v-for="child in childComponents"></li> </ul> </div> </template> <script> export default { data () { return { childComponents: ['TempVarChart.vue', 'Highlights.vue'] } }, methods: { }, computed: { }, } </script> <style> </style>
In the code, carefully observe and understand the following:
Within the <script> tag (where we obviously write some JavaScript code), we define an object that is exported (made available to other files) by default. This object contains a function data(), that returns an array object called childComponents, with its elements being names of the component files that should be nested further.
Within the <template> tag (where we write some HTML template), the thing of interest is the <ul>.
Within the unordered list, each list item should be names of the intended child components, as defined in the array object childComponents. Moreover, the list should automatically extend till the last element of the array. Seems like we should write a for-loop, isn’t it? We do that by using the v-for directive provided by Vue.js. The v-for directive:
Acts as an attribute of the <li> tag, iterates through the array, renders the names of the child components where the iterator is mentioned within the brackets (where we write the text for the list items).
The code and the explanation above forms the basis of your subsequent understanding of how the script and the template are interrelated, and how we can use the directives provided by Vue.js.
We have learnt quite a lot, but even after all these, we have one thing left to learn about seamlessly connecting components in hierarchy — passing data down from the parent component to its children. For now, we need to learn how to pass some data from src/App.vue to src/components/Content.vue, so that we can use the same techniques for the rest of the component nesting in this project.
Data trickling down from the parent to the child components might sound simple, but the devil is in the details! As briefly explained below, there are multiple steps involved in making it work:
Defining and the data For now, we want some static data to play with — an object containing hard-coded values about different aspects of weather will just be fine! We create an object called weather_data and return it from the data() function of App.vue. The weather_data object is given in the snippet below:
weather_data: { location: "California", temperature: { current: "35 C", }, highlights: { uvindex: "3", windstatus: { speed: "20 km/h", direction: "N-E", }, visibility: "12 km", }, },
Passing the data from the parent To pass the data, we need a destination where we want to send the data! In this case, the destination is the Content.vue component, and the way to implement it is to:
Assign the weather_data object to a custom attribute of the <Content> tag
Bind the attribute with the data using the v-bind: directive provided by Vue.js, which makes the attribute value dynamic (responsive to changes made in the original data).
<Content v-bind:weather_data=“weather_data”></Content>
Defining and passing the data is handled at the source side of the handshake, which in our case is the App.vue file.
The code for the App.vue file, at its current status, is given below:
<template> <div id="app"> <p>This component’s code is in </p> <Content v-bind:weather_data="weather_data"></Content> </div> </template> <script> import Content from './components/Content.vue' export default { name: 'app', components: { 'Content': Content }, data () { return { filename: 'App.vue', weather_data: { location: "California", temperature: { current: "35 C", }, highlights: { uvindex: "3", windstatus: { speed: "20 km/h", direction: "N-E", }, visibility: "12 km", }, }, } }, methods: { }, computed: { }, } </script> <style> </style>
(Large preview)
With the data defined and passed from the source (parent component), it is now the child’s responsibility to receive the data and render it appropriately, as explained in the next two steps.
Receiving the data by the child The child component, in this case Content.vue, must receive the weather_data object send to it by the parent component App.vue. Vue.js provides a mechanism to do so — all you need is an array object called props, defined in the default object exported by Content.vue. Each element of the array props is a name of the data objects it wants to receive from its parent. For now, the only data object that it is supposed to receive is weather_data from App.vue. Thus, the props array looks like:
<template> // HTML template code here </template> <script> export default { props: ["weather_data"], data () { return { // data here } }, } </script> <style> // component specific CSS here </style>
Rendering the data in the page Now that we have ensured receiving the data, the last task we need to complete is to render the data. For this example, we will directly dump the received data on the web page, just to illustrate the technique. However, in real applications (like the one we are about to build), data normally goes through lots of processing, and only the relevant parts of it are displayed in ways that suits the purpose. For example, in this project we will eventually get raw data from the weather API, clean and format it, feed the data to the data structures necessary for the charts, and then visualize it. Anyway, to display the raw data dump, we will just use the brackets that Vue understands, as shown in the snippet below:
<template> <div id="pagecontent"> // other template code here </div> </template>
It’s now time to assimilate all the bits and pieces. The code for Content.vue — at its current status — is given below:
<template> <div id="pagecontent"> <p>This child components of Content.vue are:</p> <ul> <li v-for="child in childComponents"></li> </ul> </div> </template> <script> export default { props: ["weather_data"], data () { return { childComponents: ['TempVarChart.vue', 'Highlights.vue'] } }, methods: { }, computed: { }, } </script> <style> #pagecontent { border: 1px solid black; padding: 2px; } </style>
(Large preview)
After making the changes discussed above, refresh the webpage on the browser and see how it looks. Take a moment to appreciate the complexity that Vue handles — if you modify the weather_data object in App.vue, it gets silently conveyed to Content.vue, and eventually to the browser displaying the webpage! Try by changing the value for the key location.
Although we have learned about props and data binding using static data, we will be using dynamic data collected using web APIs in the application, and will change the code accordingly.
Summary
Before we move on to the rest of the .vue files, let’s summarize what we have learnt while we wrote the code for App.vue and components/Content.vue:
The App.vue file is what we call the root component — the one that sits at the top of the component hierarchy. The rest of the .vue files represents components that are its direct child, grandchild, and so on.
The Content.vue file is a dummy component — its responsibility is to pass on the data to levels below and maintain the structural hierarchy, so that our code remains consistent with the philosophy “*what we see is what we implement*”.
The parent-child relationship of component does not happen out of thin air — you must register a component (either globally or locally, depending on the intended usage of the component), and then nest it using custom HTML tags (whose spellings are the exact same as that of the names with which the components has been registered).
Once registered and nested, data is passed on from parent to child components, and the flow is never reverse (bad things will happen if the project architecture allows backflow). The parent component is the relative source of the data, and it passes down relevant data to its children using the v-bind directive for the attributes of the custom HTML elements. The child receives the data intended for it using props, and then decides on its own what to do with the data.
For the rest of the components, we will not indulge in detailed explanation — we will just write the code based on the learnings from the above summary. The code will be self-evident, and if you get confused about the hierarchy, refer to the diagram below:
(Large preview)
The diagram says that TempVarChart.vue and Highlights.vue are the direct child of Content.vue. Thus, it might be a good idea to prepare Content.vue for sending data to those components, which we do using the code below:
<template> <div id="pagecontent"> <p>This child components of Content.vue are:</p> <ul> <li v-for="child in childComponents"></li> </ul> <temp-var-chart :tempVar="tempVar"></temp-var-chart> <today-highlights :highlights="highlights"></today-highlights> </div> </template> <script> import TempVarChart from './TempVarChart.vue' import Highlights from './Highlights.vue' export default { props: ["weather_data"], components: { 'temp-var-chart': TempVarChart, 'today-highlights': Highlights }, data () { return { childComponents: ['TempVarChart.vue', 'Highlights.vue'], tempVar: this.weather_data.temperature, highlights: this.weather_data.highlights, } }, methods: { }, computed: { }, } </script> <style> </style>
Once you save this code, you will get errors — don’t worry, it is expected. It will be fixed once you have the rest of the component files ready. If it bothers you not to be able to see the output, comment out the lines containing the custom element tags <temp-var-chart> and <today-highlights>.
For this section, this is the final code of Content.vue. For the rest of this section, we will reference to this code, and not the previous ones that we wrote for learning.
src/components/TempVarChart.vue
With its parent component Content.vue passing on the data, TempVarChart.vue must be set up to receive and render the data, as shown in the code below:
<template> <div id="tempvarchart"> <p>Temperature Information:</p> </div> </template> <script> export default { props: ["tempVar"], data () { return { } }, methods: { }, computed: { }, } </script> <style> </style>
src/components/Highlights.vue
This component will also receive data from App.vue — its parent component. After that, it should be linked with its child components, and relevant data should be passed on to them.
Let’s first see the code for receiving data from the parent:
<template> <div id="highlights"> <p>Weather Highlights:</p> </div> </template> <script> export default { props: ["highlights"], data () { return { } }, methods: { }, computed: { }, } </script> <style> </style>
At this point, the web page looks like the image below:
(Large preview)
Now we need to modify the code of Highlights.vue to register and nest its child components, followed by passing the data to children. The code for it is as follows:
<template> <div id="highlights"> <p>Weather Highlights:</p> <uv-index :highlights="highlights"></uv-index> <visibility :highlights="highlights"></visibility> <wind-status :highlights="highlights"></wind-status> </div> </template> <script> import UVIndex from './UVIndex.vue'; import Visibility from './Visibility.vue'; import WindStatus from './WindStatus.vue'; export default { props: ["highlights"], components: { 'uv-index': UVIndex, 'visibility': Visibility, 'wind-status': WindStatus, }, data () { return { } }, methods: { }, computed: { }, } </script> <style> </style>
Once you save the code and see the web page, you are expected to see errors in the Developer Console tool provided by the browser; they appear because although Highlights.vue is sending data, nobody is receiving them. We are yet to write the code for the children of Highlights.vue.
Observe that we have not done much of the data processing, i.e, we have not extracted the individual factors of weather data that goes under the Highlights section of the dashboard. We could have done that in the data() function, but we preferred to keep Highlights.vue a dumb component that just passes on the entire data dump it receives to each of the children, who then own their own extracts what is necessary for them. However, we encourage you to try out extracting data in the Highlights.vue, and send relevant data down to each child component — it’s a good practice exercise nonetheless!
src/components/UVIndex.vue
The code for this component receives the data dump of highlights from Highlights.vue, extracts the data for UV Index, and renders it on the page.
<template> <div id="uvindex"> <p>UV Index: </p> </div> </template> <script> export default { props: ["highlights"], data () { return { uvindex: this.highlights.uvindex } }, methods: { }, computed: { }, } </script> <style> </style>
src/components/Visibility.vue
The code for this component receives the data dump of highlights from Highlights.vue, extracts the data for Visibility, and renders it on the page.
<template> <div id="visibility"> <p>Visibility: </p> </div> </template> <script> export default { props: ["highlights"], data () { return { visibility: this.highlights.visibility, } }, methods: { }, computed: { }, } </script> <style> </style>
src/components/WindStatus.vue
The code for this component receives the data dump of highlights from Highlights.vue, extracts the data for Wind Status (speed and direction), and renders it on the page.
<template> <div id="windstatus"> <p>Wind Status:</p> <p>Speed — ; Direction — </p> </div> </template> <script> export default { props: ["highlights"], data () { return { speed: this.highlights.windstatus.speed, direction: this.highlights.windstatus.direction } }, methods: { }, computed: { }, } </script> <style> </style>
After adding the code for all the components, take a look at the web page on the browser.
(Large preview)
Not to dishearten, but all these toiling was just to link the components in hierarchy, and test out whether data flow is happening between them or not! In the next section, we will throw away most of the code we have written so far, and add a lot more pertaining to the actual project. However, we will certainly retain the structure and nesting of the components; the learnings from this section will allow us to build a decent dashboard with Vue.js.
4. Data Acquisition And Processing
Remember the weather_data object in App.vue? It had some hard-coded data that we used to test whether all the components are working correctly, and also to help you learn some basic aspects of Vue application without getting bogged down in the details of real-world data. However, it’s now time that we shed our shell, and step out into the real world, where data from the API will dominate most of our code.
Preparing Child Components To Receive And Process Real Data
In this section, you will get code dump for all the components except App.vue. The code will handle receiving real data from App.vue (unlike the code we wrote in the previous section to receive and render dummy data).
We strongly encourage to read the code of each component carefully, so that you form an idea of what data each of those components are expecting, and will eventually use in visualization.
Some of the code, and the overall structure, will be similar to the ones you have seen in the previous structure — so you will not face something drastically different. However, the devil is in the details! So examine the code carefully, and when you have understood them reasonably well, copy the code to the respective component files in your project.
Note: All the components in this section are in the src/components/ directory. So each time, the path will not be mentioned — only the .vue file name will be mentioned to identify the component.
Content.vue
<template> <div style="position: relative;"> <temp-var-chart :tempVar="tempVar"></temp-var-chart> <today-highlights :highlights="highlights"></today-highlights> </div> </template> <script> import TempVarChart from './TempVarChart.vue'; import Highlights from './Highlights.vue'; export default { props: ['highlights', 'tempVar'], components: { 'temp-var-chart': TempVarChart, 'today-highlights': Highlights }, } </script>
The following changes have been made from the previous code:
In the <template>, text and data within has been removed, since we are now just receiving data and passing down to the children, with no rendering specific this component.
In the export default {}:
The props have been changed to match the data objects that will be send by the parent: App.vue. The reason for changing the props is that App.vue itself will display some of the data it acquires from the weather API and other online resources, based on the search query of the user, and pass on the rest of the data. In the dummy code we wrote earlier, App.vue was passing on the entire dummy data dump, without any discrimination, and the props of Content.vue was set up accordingly.
The data() function now returns nothing, as we are not doing any data manipulation in this component.
TempVarChart.vue
This component is supposed to receive detailed temperature projections for the rest of the current day, and eventually display them using FusionCharts. But for the time being, we will display them only as text on the webpage.
<template> <div> </div> </template> <script> export default { props: ["tempVar"], components: {}, data() { return { }; }, methods: { }, }; </script> <style> </style>
Highlights.vue
<template> <div> <uv-index :highlights="highlights"></uv-index> <visibility :highlights="highlights"></visibility> <wind-status :highlights="highlights"></wind-status> </div> </template> <script> import UVIndex from './UVIndex.vue'; import Visibility from './Visibility.vue'; import WindStatus from './WindStatus.vue'; export default { props: ["highlights"], components: { 'uv-index': UVIndex, 'visibility': Visibility, 'wind-status': WindStatus, }, data () { return { } }, methods: { }, computed: { }, } </script> <style> </style>
The changes made from the previous code are:
In the <template>, the text and the data within has been removed, because this is a dumb component, just like Content.vue, whose only job is to pass on the data to children while maintaining the structural hierarchy. Remember that dumb components like Highlights.vue and Content.vue exists to maintain the parity between the visual structure of the dashboard, and the code we write.
UVIndex.vue
The changes made to the previous code are as follows:
In the <template> and <style>, the div id has been changed to uvIndex, which is more readable.
In the export default {}, the data() function now returns a string object uvIndex, whose value is extracted from the highlights object received by the component using props. This uvIndex is now temporarily used to display the value as text within the <template>. Later on, we will plug in this value to the data structure suitable for rendering a chart.
Visibility.vue
<template> <div> <p>Visibility: </p> </div> </template> <script> export default { props: ["highlights"], data () { return { visibility: this.highlights.visibility.toString() } }, methods: { }, computed: { }, } </script> <style> </style>
The only change made in this file (with respect to its previous code) is that the definition of the visibility object returned by the data() function now contains toString() at its end, since the value received from the parent will be a floating point number, which needs to be converted into string.
WindStatus.vue
<template> <div> <p>Wind Speed — </p> <p>Wind Direction — , or degree clockwise with respect to true N as 0 degree.</p> </div> </template> <script> export default { props: ["highlights"], data () { return { windSpeed: this.highlights.windStatus.windSpeed, derivedWindDirection: this.highlights.windStatus.derivedWindDirection, windDirection: this.highlights.windStatus.windDirection } }, methods: { }, computed: { }, } </script> <style> </style>
The changes made to the previous code are as follows:
Throughout the file, windstatus has been renamed as windStatus, to promote readability and also to be in sync with the the highlights object that App.vue provides with actual data.
Similar naming changes have been made for the speed and direction — the new ones are windSpeed and windDirection.
A new object derivedWindDirection has come into play (also provided by App.vue in the highlights bundle).
For now, the received data is rendered as text; later, it will be plugged in to the data structure necessary for visualization.
Testing With Dummy Data
Resorting to dummy data repeatedly might be a bit frustrating for you, but there are some good reasons behind it:
We have made a lot of changes to the code of each component, and it’s a good idea to test whether those changes are breaking the code. In other words, we should check that whether the data flow is intact, now that we are about to move to more complex parts of the project.
The real data from the online weather API will need lot of massaging, and it might be overwhelming for you to juggle between the code for data acquisition and processing, and the code for smooth data flow down the components. The idea is to keep the quantum of complexity under control, so that we have a better understanding of the errors we might face.
In this section, what we do is essentially hardcode some json data in the App.vue, which will obviously be replaced with live data in the near future. There are a lot of similarity between the dummy json structure, and the json structure we will use for the actual data. So it also provides you a rough idea of what to expect from the real data, once we encounter it.
However, we admit that this is far from the ideal approach one might adopt while building such a project from scratch. In the real world, you will often start with the real data source, play around with it a bit to understand what can and should be done to tame it, and then think about the appropriate json data structure to capture the relevant information. We intentionally shielded you from all those dirty work, since it takes you farther from the objective — learning how to use Vue.js and FusionCharts to build a dashboard.
Let’s now jump into the new code for App.vue:
<template> <div id="app"> <dashboard-content :highlights="highlights" :tempVar="tempVar"></dashboard-content> </div> </template> <script> import Content from './components/Content.vue' export default { name: 'app', components: { 'dashboard-content': Content }, data () { return { tempVar: { tempToday: [ {hour: '11.00 AM', temp: '35'}, {hour: '12.00 PM', temp: '36'}, {hour: '1.00 PM', temp: '37'}, {hour: '2.00 PM', temp: '38'}, {hour: '3.00 PM', temp: '36'}, {hour: '4.00 PM', temp: '35'}, ], }, highlights: { uvIndex: 4, visibility: 10, windStatus: { windSpeed: '30 km/h', windDirection: '30', derivedWindDirection: 'NNE', }, }, } }, methods: { }, computed: { }, } </script> <style> </style>
The changes made to the code with respect to its previous version are as follows:
The name of the child component has been changed to dashboard-content, and accordingly the custom HTML element in the <template> has been revised. Note that now we have two attributes — highlights and tempVar — instead of a single attribute that we used earlier with the custom element. Accordingly, the data associated with those attributes have also changed. What’s interesting here is that we can use the v-bind: directive, or its shorthand : (as we have done here), with multiple attributes of a custom HTML element!
The data() function now returns the filename object (that existed earlier), along with two new objects (instead of the old weather_data): tempVar and highlights. The structure of the json is appropriate for the code we have written in the child components, so that they can extract the data pieces they need from the dumps. The structures are quite self-explanatory, and you can expect them to be quite similar when we deal with live data. However, the significant change that you will encounter is the absence of hardcoding (obvious, isn’t it) — we will leave the values blank as the default state, and write code to dynamically update them based on the values we will receive from the weather API.
You have written a lot of code in this section, without seeing the actual output. Before you proceed further, take a look at the browser (restart the server with npm run dev, if necessary), and bask in the glory of your achievement. The web page that you should see at this point looks like the image below:
(Large preview)
Code For Data Acquisition And Processing
This section is going to be the meat of the project, with all the code to be written in App.vue for the following:
Location input from the user — an input box and a call-to-action button is sufficient;
Utility functions for various tasks; these functions will be called later in various parts of the component code;
Getting detailed geolocation data from Google Maps API for JavaScript;
Getting detailed weather data from the Dark Sky API;
Formatting and processing the geolocation and weather data, which will be passed on to the child components.
The subsections that follows illustrates how we can implement the tasks laid out for us in the above points. With some exceptions, most of them will follow the sequence.
Input From The User
It’s quite obvious that the action starts when the user provides the name of the place for which the weather data needs to be displayed. For this to happen, we need to implement the following:
An input box for entering the location;
A submit button that tells our application that the user has entered the location and it’s time to do the rest. We will also implement the behavior when processing starts upon hitting Enter.
The code we show below will be restricted to the HTML template part of App.vue. We will just mention the name of the method associated with the click events, and define them later in the methods object of the <script> in App.vue.
<div id="search"> <input id="location-input" type="text" ref="input" placeholder="Location?" @keyup.enter="organizeAllDetails" > <button id="search-btn" @click="organizeAllDetails"> <img src="./assets/Search.svg" width="24" height="24"> </button> </div>
Placing the above snippet in the right place is trivial — we leave it to you. However, the interesting parts of the snippet are:
@keyup.enter="organizeAllDetails"
@click="organizeAllDetails"
As you know from the earlier sections, @ is Vue’s shorthand for the directive v-on:, which is associated with some event. The new thing is “organizeAllDetails” — it’s nothing but the method that will fire once the events (pressing Enter or clicking the button) happens. We are yet to define method, and the puzzle will be complete by the end of this section.
Text Information Display Controlled By App.vue
Once the user input triggers the action and lots of data is acquired from the APIs, we encounter the inevitable question — “What to do with all these data?”. Obviously some data massaging is required, but that does not answer our question fully! We need to decide what’s the end use of the data, or more directly, which are the entities that receives different chunks of the acquired and processed data?
The child components of App.vue, based on their hierarchy and purpose, are the frontline contenders for the bulk of the data. However, we will also have some data that does not belong to any of those child components, yet are quite informative and makes the dashboard complete. We can make good use of them if we display them as text information directly controlled by App.vue, while the rest of the data are passed on to the child for getting displayed as pretty charts ultimately.
With this context in mind, let’s focus on the code for setting the stage of using text data. It’s simple HTML template at this point, on which the data will eventually come and sit.
<div id="info"> <div class="wrapper-left"> <div id="current-weather"> <span>°C</span> </div> <div id="weather-desc"></div> <div class="temp-max-min"> <div class="max-desc"> <div id="max-detail"> <i>▲</i> <span>°C</span> </div> <div id="max-summary">at </div> </div> <div class="min-desc"> <div id="min-detail"> <i>▼</i> <span>°C</span> </div> <div id="min-summary">at </div> </div> </div> </div> <div class="wrapper-right"> <div class="date-time-info"> <div id="date-desc"> <img src="./assets/calendar.svg" width="20" height="20"> </div> </div> <div class="location-info"> <div id="location-desc"> <img src="./assets/location.svg" width="10.83" height="15.83" style="opacity: 0.9;" > <div id="location-detail" class="mt-1"> Lat: <br> Long: </div> </div> </div> </div> </div>
In the above snippet, you should understand the following:
The stuff inside — they are Vue’s way of inserting dynamic data in the HTML template, before it renders in the browser. You have encountered them before, and there is nothing new or surprising. Just keep in mind that these data objects stems from the data() method in the export default() object of App.vue. They have default values that we will set according to our requirements, and then write certain methods to populate the objects with real API data.
Don’t worry for not seeing the changes on the browser — the data is not defined yet, and it’s natural for Vue to not render things that it does not know. However, once the data is set (and for now, you can even check by hard-coding the data), the text data will be controlled by App.vue.
The data() Method
The data() method is a special construct in the .vue files — it contains and returns data objects that are so crucial for the application. Recollect the generic structure of the <script> part in any .vue file — it roughly contains the following:
<script> // import statements here export default { // name, components, props, etc. data() { return { // the data that is so crucial for the application is defined here. // the data objects will have certain default values chosen by us. // The methods that we define below will manipulate the data. // Since the data is bounded to various attributes and directives, they // will update as and when the values of the data objects change. } }, methods: { // methods (objects whose values are functions) here. // bulk of dynamic stuff (the black magic part) is controlled from here. }, computed: { // computed properties here }, // other objects, as necessary } </script>
So far, you have encountered the names of some of the data objects, but are a lot more. Most of them are relevant for the child components, each of which handles a different aspect of the weather information dump. Given below is the entire data() method that we will need for this project — you will have a fair idea about what data we are expecting from the APIs, and how we are disseminating the data, based on the nomenclature of the objects.
data() { return { weatherDetails: false, location: '', // raw location from input lat: '', // raw latitude from google maps api response long: '', // raw longitude from google maps api response completeWeatherApi: '', // weather api string with lat and long rawWeatherData: '', // raw response from weather api currentWeather: { full_location: '', // for full address formatted_lat: '', // for N/S formatted_long: '', // for E/W time: '', temp: '', todayHighLow: { todayTempHigh: '', todayTempHighTime: '', todayTempLow: '', todayTempLowTime: '' }, summary: '', possibility: '' }, tempVar: { tempToday: [ // gets added dynamically by this.getSetHourlyTempInfoToday() ], }, highlights: { uvIndex: '', visibility: '', windStatus: { windSpeed: '', windDirection: '', derivedWindDirection: '' }, } }; },
As you can see, in most cases the default value is empty, because that will suffice at this point. Methods will be written for manipulating the data and filling it up with appropriate values, before it is rendered or passed on to the child components.
Methods in App.vue
For .vue files, the methods are generally written as values of keys nested in the methods { } object. Their primary role is to manipulate the data objects of the component. We will write the methods in App.vue keeping the same philosophy in mind. However, based on their purpose, we can categorize the methods of App.vue into the following:
Utility methods
Action/Event oriented methods
Data acquisition methods
Data processing methods
High level glue methods
It’s important that you understand this — we are presenting the methods to you on a platter because we have already figured out how the APIs work, what data they give, and how we should use the data in our project. It’s not that we pulled the methods out of thin air, and wrote some arcane code to deal with the data. For the purpose of learning, it’s a good exercise to diligently read and understand the code for the methods and data. However, when faced with a new project that you have to build from scratch, you must do all the dirty work yourself, and that means experimenting a lot with the APIs — their programmatic access and their data structure, before glueing them seamlessly with the data structure that your project demands. You will not have any hand holding, and there will be frustrating moments, but that’s all part of maturing as a developer.
In the following subsections, we will explain each of the method types, and also show the implementation of the methods belonging to that category. The method names are quite self-explanatory about their purpose, and so is their implementation, which we believe you will find to be easy enough to follow. However, before that, recollect the general scheme of writing methods in .vue files:
<script> // import statements here export default { // name, components, props, etc. data() { return { // the data that is so crucial for the application is defined here. } }, methods: { // methods (objects whose values are functions) here. // bulk of dynamic stuff (the black magic part) is controlled from here. method_1: function(arg_1) { }, method_2: function(arg_1, arg_2) { }, method_3: function(arg_1) { }, ……. }, computed: { // computed properties here }, // other objects, as necessary } </script>
Utility Methods
The utility methods, as the name suggests, are methods written primarily for the purpose of modularizing repetitive code used for fringe tasks. They are called by other methods when necessary. Given below are the utility methods for App.vue:
convertToTitleCase: function(str) { str = str.toLowerCase().split(' '); for (var i = 0; i
// To format the “possibility” (of weather) string obtained from the weather API formatPossibility: function(str) { str = str.toLowerCase().split('-'); for (var i = 0; i
// To convert Unix timestamps according to our convenience unixToHuman: function(timezone, timestamp) { /* READ THIS BEFORE JUDGING & DEBUGGING For any location beyond the arctic circle and the antarctic circle, the goddamn weather api does not return certain keys/values in each of this.rawWeatherData.daily.data[some_array_index]. Due to this, console throws up an error. The code is correct, the problem is with the API. May be later on I will add some padding to tackle missing values. */ var moment = require('moment-timezone'); // for handling date & time var decipher = new Date(timestamp * 1000); var human = moment(decipher) .tz(timezone) .format('llll'); var timeArray = human.split(' '); var timeNumeral = timeArray[4]; var timeSuffix = timeArray[5]; var justTime = timeNumeral + ' ' + timeSuffix; var monthDateArray = human.split(','); var monthDate = monthDateArray[1].trim(); return { fullTime: human, onlyTime: justTime, onlyMonthDate: monthDate }; },
// To convert temperature from fahrenheit to celcius fahToCel: function(tempInFahrenheit) { var tempInCelcius = Math.round((5 / 9) * (tempInFahrenheit — 32)); return tempInCelcius; },
// To convert the air pressure reading from millibar to kilopascal milibarToKiloPascal: function(pressureInMilibar) { var pressureInKPA = pressureInMilibar * 0.1; return Math.round(pressureInKPA); },
// To convert distance readings from miles to kilometers mileToKilometer: function(miles) { var kilometer = miles * 1.60934; return Math.round(kilometer); },
// To format the wind direction based on the angle deriveWindDir: function(windDir) { var wind_directions_array = [ { minVal: 0, maxVal: 30, direction: 'N' }, { minVal: 31, maxVal: 45, direction: 'NNE' }, { minVal: 46, maxVal: 75, direction: 'NE' }, { minVal: 76, maxVal: 90, direction: 'ENE' }, { minVal: 91, maxVal: 120, direction: 'E' }, { minVal: 121, maxVal: 135, direction: 'ESE' }, { minVal: 136, maxVal: 165, direction: 'SE' }, { minVal: 166, maxVal: 180, direction: 'SSE' }, { minVal: 181, maxVal: 210, direction: 'S' }, { minVal: 211, maxVal: 225, direction: 'SSW' }, { minVal: 226, maxVal: 255, direction: 'SW' }, { minVal: 256, maxVal: 270, direction: 'WSW' }, { minVal: 271, maxVal: 300, direction: 'W' }, { minVal: 301, maxVal: 315, direction: 'WNW' }, { minVal: 316, maxVal: 345, direction: 'NW' }, { minVal: 346, maxVal: 360, direction: 'NNW' } ]; var wind_direction = ''; for (var i = 0; i = wind_directions_array[i].minVal && windDir
Although we haven’t implemented it, you can take out the utility methods from the .vue file, and put it in a separate JavaScript file. All you need to do is import the .js file at the start of the script part in the .vue file, and you should be good to go. Such approach works really well and keeps the code clean, especially in big applications where you might use lots of methods that are better grouped together based on their purpose. You can apply this approach to all of the method groups listed in this article, and see the effect itself. However, we suggest you do that exercise once you have followed the course presented here, so that you have the big picture understanding of all the parts working in complete sync, and also have a working piece of software which you can refer to, once something breaks while experimenting.
Action/Event Oriented Methods
These methods are generally executed when we need to take an action corresponding to an event. Depending on the case, the event might be triggered from an user interaction, or programmatically. In the App.vue file, these methods sit below the utility methods.
makeInputEmpty: function() { this.$refs.input.value = ''; },
makeTempVarTodayEmpty: function() { this.tempVar.tempToday = []; },
detectEnterKeyPress: function() { var input = this.$refs.input; input.addEventListener('keyup', function(event) { event.preventDefault(); var enterKeyCode = 13; if (event.keyCode === enterKeyCode) { this.setHitEnterKeyTrue(); } }); },
locationEntered: function() { var input = this.$refs.input; if (input.value === '') { this.location = "New York"; } else { this.location = this.convertToTitleCase(input.value); } this.makeInputEmpty(); this.makeTempVarTodayEmpty(); },
One interesting thing in some of the above code snippets is the use of $ref. In simple terms, it’s Vue’s way of associating the code statement containing it, to the HTML construct it is supposed to affect (for more information, read the official guide). For example, the methods makeInputEmpty() and detectEnterKeyPress() affects the input box, because in the HTML of the input box we have mentioned the value of the attribute ref as input.
Data Acquisition Methods
We are using the following two APIs in our project:
Google Maps Geocoder API This API is for getting the coordinates of the location that the user searches. You will need an API key for yourself, which you can get by following the documentation in the given link. For now, you can use the API key used by FusionCharts, but we request you not to abuse it and get a key of your own. We refer to the JavaScript API from the index.html of this project, and we shall use the constructors provided by it for our code in the App.vue file.
The Dark Sky Weather API This API is for getting the weather data corresponding to the coordinates. However, we won’t be using it directly; we will wrap it within an URL that redirects through one of the FusionCharts’s server. The reason is that if you send a GET request to the API from an entirely client-end application such as ours, it results in the frustrating CORS error (more information here and here).
Important Note: Since we have used Google Maps and Dark Sky APIs, Both these APIs have their own API keys which we have shared with you in this article. This will help you focus on client-side developments rather than the headache of backend implementation. However, we recommend you to create your own keys, because our APIs keys will come with limits and if these limits exceed you won't be able to try the application by yourself.
For Google Maps, go to this article to get your API key. For Dark Sky API, visit https://darksky.net/dev to create your API key and respective endpoints.
With the context in mind, let’s see the implementation of the data acquisition methods for our project.
getCoordinates: function() { this.locationEntered(); var loc = this.location; var coords; var geocoder = new google.maps.Geocoder(); return new Promise(function(resolve, reject) { geocoder.geocode({ address: loc }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { this.lat = results[0].geometry.location.lat(); this.long = results[0].geometry.location.lng(); this.full_location = results[0].formatted_address; coords = { lat: this.lat, long: this.long, full_location: this.full_location }; resolve(coords); } else { alert("Oops! Couldn't get data for the location"); } }); }); },
/* The coordinates that Google Maps Geocoder API returns are way too accurate for our requirements. We need to bring it into shape before passing the coordinates on to the weather API. Although this is a data processing method in its own right, we can’t help mentioning it right now, because the data acquisition method for the weather API has dependency on the output of this method. */ setFormatCoordinates: async function() { var coordinates = await this.getCoordinates(); this.lat = coordinates.lat; this.long = coordinates.long; this.currentWeather.full_location = coordinates.full_location; // Remember to beautify lat for N/S if (coordinates.lat > 0) { this.currentWeather.formatted_lat = (Math.round(coordinates.lat * 10000) / 10000).toString() + '°N'; } else if (coordinates.lat 0) { this.currentWeather.formatted_long = (Math.round(coordinates.long * 10000) / 10000).toString() + '°E'; } else if (coordinates.long
/* This method dynamically creates the the correct weather API query URL, based on the formatted latitude and longitude. The complete URL is then fed to the method querying for weather data. Notice that the base URL used in this method (without the coordinates) points towards a FusionCharts server — we must redirect our GET request to the weather API through a server to avoid the CORS error. */ fixWeatherApi: async function() { await this.setFormatCoordinates(); var weatherApi = 'https://csm.fusioncharts.com/files/assets/wb/wb-data.php?src=darksky&lat=' + this.lat + '&long=' + this.long; this.completeWeatherApi = weatherApi; },
fetchWeatherData: async function() { await this.fixWeatherApi(); var axios = require('axios'); // for handling weather api promise var weatherApiResponse = await axios.get(this.completeWeatherApi); if (weatherApiResponse.status === 200) { this.rawWeatherData = weatherApiResponse.data; } else { alert('Hmm... Seems like our weather experts are busy!'); } },
Through these methods, we have introduced the concept of async-await in our code. If you have been a JavaScript developer for some time now, you must be familiar with the callback hell, which is a direct consequence of the asynchronous way JavaScript is written. ES6 allows us to bypass the cumbersome nested callbacks, and our code becomes much cleaner if we write JavaScript in a synchronous way, using the async-await technique. However, there is a downside. It takes away the speed that asynchronous code gives us, especially for the portions of the code that deals with data being exchanged over the internet. Since this is not a mission-critical application with low latency requirements, and our primary aim is to learn stuff, the clean code is much more preferable over the slightly fast code.
Data Processing Methods
Now that we have the methods that will bring the data to us, we need to prepare the ground for properly receiving and processing the data. Safety nets must be cast, and there should be no spills — data is the new gold (OK, that might be an exaggeration in our context)! Enough with the fuss, let’s get to the point.
Technically, the methods we implement in this section are aimed at getting the data out of the acquisition methods and the data objects in App.vue, and sometimes setting the data objects to certain values that suits the purpose.
getTimezone: function() { return this.rawWeatherData.timezone; },
getSetCurrentTime: function() { var currentTime = this.rawWeatherData.currently.time; var timezone = this.getTimezone(); this.currentWeather.time = this.unixToHuman( timezone, currentTime ).fullTime; },
getSetSummary: function() { var currentSummary = this.convertToTitleCase( this.rawWeatherData.currently.summary ); if (currentSummary.includes(' And')) { currentSummary = currentSummary.replace(' And', ','); } this.currentWeather.summary = currentSummary; },
getSetPossibility: function() { var possible = this.formatPossibility(this.rawWeatherData.daily.icon); if (possible.includes(' And')) { possible = possible.replace(' And', ','); } this.currentWeather.possibility = possible; },
getSetCurrentTemp: function() { var currentTemp = this.rawWeatherData.currently.temperature; this.currentWeather.temp = this.fahToCel(currentTemp); },
getTodayDetails: function() { return this.rawWeatherData.daily.data[0]; },
getSetTodayTempHighLowWithTime: function() { var timezone = this.getTimezone(); var todayDetails = this.getTodayDetails(); this.currentWeather.todayHighLow.todayTempHigh = this.fahToCel( todayDetails.temperatureMax ); this.currentWeather.todayHighLow.todayTempHighTime = this.unixToHuman( timezone, todayDetails.temperatureMaxTime ).onlyTime; this.currentWeather.todayHighLow.todayTempLow = this.fahToCel( todayDetails.temperatureMin ); this.currentWeather.todayHighLow.todayTempLowTime = this.unixToHuman( timezone, todayDetails.temperatureMinTime ).onlyTime; },
getHourlyInfoToday: function() { return this.rawWeatherData.hourly.data; },
getSetHourlyTempInfoToday: function() { var unixTime = this.rawWeatherData.currently.time; var timezone = this.getTimezone(); var todayMonthDate = this.unixToHuman(timezone, unixTime).onlyMonthDate; var hourlyData = this.getHourlyInfoToday(); for (var i = 0; i
getSetUVIndex: function() { var uvIndex = this.rawWeatherData.currently.uvIndex; this.highlights.uvIndex = uvIndex; },
getSetVisibility: function() { var visibilityInMiles = this.rawWeatherData.currently.visibility; this.highlights.visibility = this.mileToKilometer(visibilityInMiles); },
getSetWindStatus: function() { var windSpeedInMiles = this.rawWeatherData.currently.windSpeed; this.highlights.windStatus.windSpeed = this.mileToKilometer( windSpeedInMiles ); var absoluteWindDir = this.rawWeatherData.currently.windBearing; this.highlights.windStatus.windDirection = absoluteWindDir; this.highlights.windStatus.derivedWindDirection = this.deriveWindDir( absoluteWindDir ); },
High Level Glue Methods
With the utility, acquisition, and processing methods out of our way, we are now left with the task of orchestrating the entire thing. We do that by creating high level glue methods, that essentially calls the methods written above in a particular sequence, so that the entire operation is executed seamlessly.
// Top level for info section // Data in this.currentWeather organizeCurrentWeatherInfo: function() { // data in this.currentWeather /* Coordinates and location is covered (get & set) in: — this.getCoordinates() — this.setFormatCoordinates() There are lots of async-await involved there. So it's better to keep them there. */ this.getSetCurrentTime(); this.getSetCurrentTemp(); this.getSetTodayTempHighLowWithTime(); this.getSetSummary(); this.getSetPossibility(); },
// Top level for highlights organizeTodayHighlights: function() { // top level for highlights this.getSetUVIndex(); this.getSetVisibility(); this.getSetWindStatus(); },
// Top level organization and rendering organizeAllDetails: async function() { // top level organization await this.fetchWeatherData(); this.organizeCurrentWeatherInfo(); this.organizeTodayHighlights(); this.getSetHourlyTempInfoToday(); },
mounted
Vue provides instance lifecycle hooks — properties that are essentially methods, and gets triggered when the instance lifecycle reaches that stage. For example, created, mounted, beforeUpdate, etc., are all very useful lifecycle hooks that allows the programmer to control the instance at a much more granular level than that would have been possible otherwise.
In the code of a Vue component, these lifecycle hooks are implemented just like you would for any other prop. For example:
<template> </template> <script> // import statements export default { data() { return { // data objects here } }, methods: { // methods here }, mounted: function(){ // function body here }, } </script> <style> </style>
Armed with this new understanding, take a look at the code below for the mounted prop of App.vue:
mounted: async function() { this.location = "New York"; await this.organizeAllDetails(); }
Complete Code For App.vue
We have covered a lot of ground in this section, and the last few sections have given you things in bits and pieces. However, it’s important that you have the complete, assembled code for App.vue (subject to further modifications in subsequent sections). Here it goes:
<template> <div id="ancestor"> <div class="container-fluid" id="app"> <div class="row"> <div id="sidebar" class="col-md-3 col-sm-4 col-xs-12 sidebar"> <div id="search"> <input id="location-input" type="text" ref="input" placeholder="Location?" @keyup.enter="organizeAllDetails" > <button id="search-btn" @click="organizeAllDetails"> <img src="./assets/Search.svg" width="24" height="24"> </button> </div> <div id="info"> <div class="wrapper-left"> <div id="current-weather"> <span>°C</span> </div> <div id="weather-desc"></div> <div class="temp-max-min"> <div class="max-desc"> <div id="max-detail"> <i>▲</i> <span>°C</span> </div> <div id="max-summary">at </div> </div> <div class="min-desc"> <div id="min-detail"> <i>▼</i> <span>°C</span> </div> <div id="min-summary">at </div> </div> </div> </div> <div class="wrapper-right"> <div class="date-time-info"> <div id="date-desc"> <img src="./assets/calendar.svg" width="20" height="20"> </div> </div> <div class="location-info"> <div id="location-desc"> <img src="./assets/location.svg" width="10.83" height="15.83" style="opacity: 0.9;" > <div id="location-detail" class="mt-1"> Lat: <br> Long: </div> </div> </div> </div> </div> </div> <dashboard-content class="col-md-9 col-sm-8 col-xs-12 content" id="dashboard-content" :highlights="highlights" :tempVar="tempVar" ></dashboard-content> </div> </div> </div> </template> <script> import Content from './components/Content.vue'; export default { name: 'app', props: [], components: { 'dashboard-content': Content }, data() { return { weatherDetails: false, location: '', // raw location from input lat: '', // raw latitude from google maps api response long: '', // raw longitude from google maps api response completeWeatherApi: '', // weather api string with lat and long rawWeatherData: '', // raw response from weather api currentWeather: { full_location: '', // for full address formatted_lat: '', // for N/S formatted_long: '', // for E/W time: '', temp: '', todayHighLow: { todayTempHigh: '', todayTempHighTime: '', todayTempLow: '', todayTempLowTime: '' }, summary: '', possibility: '' }, tempVar: { tempToday: [ // gets added dynamically by this.getSetHourlyTempInfoToday() ], }, highlights: { uvIndex: '', visibility: '', windStatus: { windSpeed: '', windDirection: '', derivedWindDirection: '' }, } }; }, methods: { // Some utility functions convertToTitleCase: function(str) { str = str.toLowerCase().split(' '); for (var i = 0; i < str.length; i++) { str[i] = str[i].charAt(0).toUpperCase() + str[i].slice(1); } return str.join(' '); }, formatPossibility: function(str) { str = str.toLowerCase().split('-'); for (var i = 0; i < str.length; i++) { str[i] = str[i].charAt(0).toUpperCase() + str[i].slice(1); } return str.join(' '); }, unixToHuman: function(timezone, timestamp) { /* READ THIS BEFORE JUDGING & DEBUGGING For any location beyond the arctic circle and the antarctic circle, the goddamn weather api does not return certain keys/values in each of this.rawWeatherData.daily.data[some_array_index]. Due to this, console throws up an error. The code is correct, the problem is with the API. May be later on I will add some padding to tackle missing values. */ var moment = require('moment-timezone'); // for handling date & time var decipher = new Date(timestamp * 1000); var human = moment(decipher) .tz(timezone) .format('llll'); var timeArray = human.split(' '); var timeNumeral = timeArray[4]; var timeSuffix = timeArray[5]; var justTime = timeNumeral + ' ' + timeSuffix; var monthDateArray = human.split(','); var monthDate = monthDateArray[1].trim(); return { fullTime: human, onlyTime: justTime, onlyMonthDate: monthDate }; }, fahToCel: function(tempInFahrenheit) { var tempInCelcius = Math.round((5 / 9) * (tempInFahrenheit — 32)); return tempInCelcius; }, milibarToKiloPascal: function(pressureInMilibar) { var pressureInKPA = pressureInMilibar * 0.1; return Math.round(pressureInKPA); }, mileToKilometer: function(miles) { var kilometer = miles * 1.60934; return Math.round(kilometer); }, deriveWindDir: function(windDir) { var wind_directions_array = [ { minVal: 0, maxVal: 30, direction: 'N' }, { minVal: 31, maxVal: 45, direction: 'NNE' }, { minVal: 46, maxVal: 75, direction: 'NE' }, { minVal: 76, maxVal: 90, direction: 'ENE' }, { minVal: 91, maxVal: 120, direction: 'E' }, { minVal: 121, maxVal: 135, direction: 'ESE' }, { minVal: 136, maxVal: 165, direction: 'SE' }, { minVal: 166, maxVal: 180, direction: 'SSE' }, { minVal: 181, maxVal: 210, direction: 'S' }, { minVal: 211, maxVal: 225, direction: 'SSW' }, { minVal: 226, maxVal: 255, direction: 'SW' }, { minVal: 256, maxVal: 270, direction: 'WSW' }, { minVal: 271, maxVal: 300, direction: 'W' }, { minVal: 301, maxVal: 315, direction: 'WNW' }, { minVal: 316, maxVal: 345, direction: 'NW' }, { minVal: 346, maxVal: 360, direction: 'NNW' } ]; var wind_direction = ''; for (var i = 0; i < wind_directions_array.length; i++) { if ( windDir >= wind_directions_array[i].minVal && windDir <= wind_directions_array[i].maxVal ) { wind_direction = wind_directions_array[i].direction; } } return wind_direction; }, // Some basic action oriented functions makeInputEmpty: function() { this.$refs.input.value = ''; }, makeTempVarTodayEmpty: function() { this.tempVar.tempToday = []; }, detectEnterKeyPress: function() { var input = this.$refs.input; input.addEventListener('keyup', function(event) { event.preventDefault(); var enterKeyCode = 13; if (event.keyCode === enterKeyCode) { this.setHitEnterKeyTrue(); } }); }, locationEntered: function() { var input = this.$refs.input; if (input.value === '') { this.location = "New York"; } else { this.location = this.convertToTitleCase(input.value); } this.makeInputEmpty(); this.makeTempVarTodayEmpty(); }, getCoordinates: function() { this.locationEntered(); var loc = this.location; var coords; var geocoder = new google.maps.Geocoder(); return new Promise(function(resolve, reject) { geocoder.geocode({ address: loc }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { this.lat = results[0].geometry.location.lat(); this.long = results[0].geometry.location.lng(); this.full_location = results[0].formatted_address; coords = { lat: this.lat, long: this.long, full_location: this.full_location }; resolve(coords); } else { alert("Oops! Couldn't get data for the location"); } }); }); }, // Some basic asynchronous functions setFormatCoordinates: async function() { var coordinates = await this.getCoordinates(); this.lat = coordinates.lat; this.long = coordinates.long; this.currentWeather.full_location = coordinates.full_location; // Remember to beautify lat for N/S if (coordinates.lat > 0) { this.currentWeather.formatted_lat = (Math.round(coordinates.lat * 10000) / 10000).toString() + '°N'; } else if (coordinates.lat < 0) { this.currentWeather.formatted_lat = (-1 * (Math.round(coordinates.lat * 10000) / 10000)).toString() + '°S'; } else { this.currentWeather.formatted_lat = ( Math.round(coordinates.lat * 10000) / 10000 ).toString(); } // Remember to beautify long for N/S if (coordinates.long > 0) { this.currentWeather.formatted_long = (Math.round(coordinates.long * 10000) / 10000).toString() + '°E'; } else if (coordinates.long < 0) { this.currentWeather.formatted_long = (-1 * (Math.round(coordinates.long * 10000) / 10000)).toString() + '°W'; } else { this.currentWeather.formatted_long = ( Math.round(coordinates.long * 10000) / 10000 ).toString(); } }, fixWeatherApi: async function() { await this.setFormatCoordinates(); var weatherApi = 'https://csm.fusioncharts.com/files/assets/wb/wb-data.php?src=darksky&lat=' + this.lat + '&long=' + this.long; this.completeWeatherApi = weatherApi; }, fetchWeatherData: async function() { await this.fixWeatherApi(); var axios = require('axios'); // for handling weather api promise var weatherApiResponse = await axios.get(this.completeWeatherApi); if (weatherApiResponse.status === 200) { this.rawWeatherData = weatherApiResponse.data; } else { alert('Hmm... Seems like our weather experts are busy!'); } }, // Get and set functions; often combined, because they are short // For basic info — left panel/sidebar getTimezone: function() { return this.rawWeatherData.timezone; }, getSetCurrentTime: function() { var currentTime = this.rawWeatherData.currently.time; var timezone = this.getTimezone(); this.currentWeather.time = this.unixToHuman( timezone, currentTime ).fullTime; }, getSetSummary: function() { var currentSummary = this.convertToTitleCase( this.rawWeatherData.currently.summary ); if (currentSummary.includes(' And')) { currentSummary = currentSummary.replace(' And', ','); } this.currentWeather.summary = currentSummary; }, getSetPossibility: function() { var possible = this.formatPossibility(this.rawWeatherData.daily.icon); if (possible.includes(' And')) { possible = possible.replace(' And', ','); } this.currentWeather.possibility = possible; }, getSetCurrentTemp: function() { var currentTemp = this.rawWeatherData.currently.temperature; this.currentWeather.temp = this.fahToCel(currentTemp); }, getTodayDetails: function() { return this.rawWeatherData.daily.data[0]; }, getSetTodayTempHighLowWithTime: function() { var timezone = this.getTimezone(); var todayDetails = this.getTodayDetails(); this.currentWeather.todayHighLow.todayTempHigh = this.fahToCel( todayDetails.temperatureMax ); this.currentWeather.todayHighLow.todayTempHighTime = this.unixToHuman( timezone, todayDetails.temperatureMaxTime ).onlyTime; this.currentWeather.todayHighLow.todayTempLow = this.fahToCel( todayDetails.temperatureMin ); this.currentWeather.todayHighLow.todayTempLowTime = this.unixToHuman( timezone, todayDetails.temperatureMinTime ).onlyTime; }, getHourlyInfoToday: function() { return this.rawWeatherData.hourly.data; }, getSetHourlyTempInfoToday: function() { var unixTime = this.rawWeatherData.currently.time; var timezone = this.getTimezone(); var todayMonthDate = this.unixToHuman(timezone, unixTime).onlyMonthDate; var hourlyData = this.getHourlyInfoToday(); for (var i = 0; i < hourlyData.length; i++) { var hourlyTimeAllTypes = this.unixToHuman(timezone, hourlyData[i].time); var hourlyOnlyTime = hourlyTimeAllTypes.onlyTime; var hourlyMonthDate = hourlyTimeAllTypes.onlyMonthDate; if (todayMonthDate === hourlyMonthDate) { var hourlyObject = { hour: '', temp: '' }; hourlyObject.hour = hourlyOnlyTime; hourlyObject.temp = this.fahToCel(hourlyData[i].temperature).toString(); this.tempVar.tempToday.push(hourlyObject); /* Since we are using array.push(), we are just adding elements at the end of the array. Thus, the array is not getting emptied first when a new location is entered. to solve this problem, a method this.makeTempVarTodayEmpty() has been created, and called from this.locationEntered(). */ } } /* To cover the edge case where the local time is between 10 — 12 PM, and therefore there are only two elements in the array this.tempVar.tempToday. We need to add the points for minimum temperature and maximum temperature so that the chart gets generated with atleast four points. */ if (this.tempVar.tempToday.length <= 2) { var minTempObject = { hour: this.currentWeather.todayHighLow.todayTempHighTime, temp: this.currentWeather.todayHighLow.todayTempHigh }; var maxTempObject = { hour: this.currentWeather.todayHighLow.todayTempLowTime, temp: this.currentWeather.todayHighLow.todayTempLow }; /* Typically, lowest temp are at dawn, highest temp is around mid day. Thus we can safely arrange like min, max, temp after 10 PM. */ // array.unshift() adds stuff at the beginning of the array. // the order will be: min, max, 10 PM, 11 PM. this.tempVar.tempToday.unshift(maxTempObject, minTempObject); } }, // For Today Highlights getSetUVIndex: function() { var uvIndex = this.rawWeatherData.currently.uvIndex; this.highlights.uvIndex = uvIndex; }, getSetVisibility: function() { var visibilityInMiles = this.rawWeatherData.currently.visibility; this.highlights.visibility = this.mileToKilometer(visibilityInMiles); }, getSetWindStatus: function() { var windSpeedInMiles = this.rawWeatherData.currently.windSpeed; this.highlights.windStatus.windSpeed = this.mileToKilometer( windSpeedInMiles ); var absoluteWindDir = this.rawWeatherData.currently.windBearing; this.highlights.windStatus.windDirection = absoluteWindDir; this.highlights.windStatus.derivedWindDirection = this.deriveWindDir( absoluteWindDir ); }, // top level for info section organizeCurrentWeatherInfo: function() { // data in this.currentWeather /* Coordinates and location is covered (get & set) in: — this.getCoordinates() — this.setFormatCoordinates() There are lots of async-await involved there. So it's better to keep them there. */ this.getSetCurrentTime(); this.getSetCurrentTemp(); this.getSetTodayTempHighLowWithTime(); this.getSetSummary(); this.getSetPossibility(); }, organizeTodayHighlights: function() { // top level for highlights this.getSetUVIndex(); this.getSetVisibility(); this.getSetWindStatus(); }, // topmost level orchestration organizeAllDetails: async function() { // top level organization await this.fetchWeatherData(); this.organizeCurrentWeatherInfo(); this.organizeTodayHighlights(); this.getSetHourlyTempInfoToday(); }, }, mounted: async function() { this.location = "New York"; await this.organizeAllDetails(); } }; </script>
And finally, after so much of patience and hard work, you can see the data flow with its raw power! Visit the application on the browser, refresh the page, search for a location in the application’s search box, and hit Enter!
(Large preview)
Now that we are done with all the heavy lifting, take a break. The subsequent sections focus on using the data to create charts that are beautiful and informative, followed by giving our ugly looking application a much deserved grooming session using CSS.
5. Data Visualization With FusionCharts
Fundamental Considerations For Charts
For the end user, the essence of a dashboard is essentially this: a collection of the filtered and carefully curated information on a particular topic, conveyed through visual/graphic instruments for quick ingestion. They don’t care about the subtleties of your data pipeline engineering, or how aesthetic your code is — all they want is a high-level view in 3 seconds. Therefore, our crude application displaying text data means nothing to them, and it’s high time we implement mechanisms to wrap the data with charts.
However, before we dive deep into the implementation of charts, let’s consider some pertinent questions and the possible answers from our perspective:
What type of charts are appropriate for the type of data we are dealing with? Well, the answer has two aspects — the context, and the purpose. By context, we mean the type of data, and it’s overall fit in the scheme of bigger things, bounded by the scope and audience of the project. And by purpose, we essentially mean “what we want to emphasize on?”. For example, we can represent today’s temperature at different times of the day by using a Column chart (vertical columns of equal width, with height proportional to the value the column represents). However, we are rarely interested in the individual values, but rather the overall variation and trend throughout the data. To suit the purpose, it is in our best interest to use a Line chart, and we will do that shortly.
What should be kept in mind before selecting a charting library? Since we are doing a project predominantly using JavaScript based technologies, it’s a no-brainer that any charting library that we choose for our project should be a native of the JavaScript world. With that basic premise in mind, we should consider the following before zeroing down on any particular library:
Support for the frameworks of our choice, which in this case, is Vue.js. A project can be developed in other popular JavaScript frameworks like React, or Angular — check the support of the charting library for your favorite framework. Also, support for other popular programming languages like Python, Java, C++, .Net (AS and VB), especially when the project involves some serious backend stuff, must be considered.
Availability of charts types and features, since it is almost impossible to know beforehand what will be final shape and purpose of the data in the project (especially if the requirements are regulated by your clients in a professional setting). In this case, you should cast your net wide, and choose a charting library that has the widest collection of charts. More importantly, to differentiate your project from others, the library should have have enough features in the form of configurable chart attributes, so that you can fine-tune and customize most aspects of the charts and the right level of granularity. Also, the default chart configurations should be sensible, and the library documentation has to be top notch, for reasons that’s obvious to professional developers.
Learning curve, support community, and balance must also be taken into consideration, especially when you are new to data visualization. On one end of the spectrum, you have proprietary tools like Tableau and Qlickview that costs a bomb, has smooth learning curve, but also comes with so many limitations in terms of customizability, integration, and deployment. On the other end there is d3.js — vast, free (open source), and customizable to its core, but you have to pay the price of a very steep learning curve to be able to do anything productive with the library.
What you need is the sweet spot — the right balance between productivity, coverage, customizability, learning curve, and off course, cost. We nudge you to take a look at FusionCharts — the world’s most comprehensive and enterprise-ready JavaScript charting library for the web and mobile, that we will be using in this project for creating charts.
Introduction To FusionCharts
FusionCharts is used worldwide as the go-to JavaScript charting library by millions of developers spread across hundreds of countries around the globe. Technically, it’s as loaded and configurable as it can be, with support for integrating it with almost any popular tech stack used for web based projects. Using FusionCharts commercially requires a license, and you have to pay for the license depending on your use case (please contact sales if you are curious). However, we are using FusionCharts in this projects just to try out a few things, and therefore the non-licensed version (comes with a small watermark in your charts, and a few other restrictions). Using the non-licensed version is perfectly fine when you are trying out the charts and using it in your non-commercial or personal projects. If you have plans to deploy the application commercially, please ensure that you have a license from FusionCharts.
Since this is a project involving Vue.js, we will need two modules that needs to be installed, if not done earlier:
The fusioncharts module, because it contains everything you will need for creating the charts
The vue-fusioncharts module, which is essentially a wrapper for fusioncharts, so that it can be used in a Vue.js project
If you have not installed them earlier (as instructed in the third section), install them by executing the following command from the project’s root directory:
npm install fusioncharts vue-fusioncharts --save
Next, ensure that the src/main.js file of the project has the following code (also mentioned in section 3):
import Vue from 'vue'; import App from './App.vue'; import FusionCharts from 'fusioncharts'; import Charts from 'fusioncharts/fusioncharts.charts'; import Widgets from 'fusioncharts/fusioncharts.widgets'; import PowerCharts from 'fusioncharts/fusioncharts.powercharts'; import FusionTheme from 'fusioncharts/themes/fusioncharts.theme.fusion'; import VueFusionCharts from 'vue-fusioncharts'; Charts(FusionCharts); PowerCharts(FusionCharts); Widgets(FusionCharts); FusionTheme(FusionCharts); Vue.use(VueFusionCharts, FusionCharts); new Vue({ el: '#app', render: h => h(App) })
Perhaps the most critical line in the above snippet is the following:
Vue.use(VueFusionCharts, FusionCharts)
It instructs Vue to use the vue-fusioncharts module for making sense of many things in the project that are apparently not explicitly defined by us, but is defined in the module itself. Also, this type of statement implies global declaration, by which we mean that anywhere Vue encounters anything strange in the code of our project (things that we have not explicitly defined about using FusionCharts), it will at least look once in the vue-fusioncharts and fusioncharts node modules for their definitions, before throwing up errors. If we would have used FusionCharts in an isolated part of our project (not using it in almost all of the component files), then perhaps local declaration would have made more sense.
With that, you are all set to use FusionCharts in the project. We will be using quite a few variety of charts, the choice being dependent on the aspect of the weather data that we want to visualize. Also, we will get to see the interplay of data binding, custom components, and watchers in action.
General Scheme For Using Fusioncharts In .vue Files
In this section, we will explain the general idea of using FusionCharts for creating various charts in the .vue files. But first, let’s see the pseudocode that schematically illustrates the core idea.
<template> <div> <fusioncharts :attribute_1="data_object_1" :attribute_2="data_object_2" … … ... > </fusioncharts> </div> </template> <script> export default { props: ["data_prop_received_by_the_component"], components: {}, data() { return { data_object_1: "value_1", data_object_2: "value_2", … … }; }, methods: {}, computed: {}, watch: { data_prop_received_by_the_component: { handler: function() { // some code/logic, mainly data manipulation based }, deep: true } } }; </script> <style> // component specific special CSS code here </style>
Let’s understand different parts of the above pseudocode:
In the <template>, within the top level <div> (that’s pretty much mandatory for the template HTML code of every component), we have the custom component <fusioncharts>. We have the definition of the component contained in the vue-fusioncharts Node module that we have installed for this project. Internally, vue-fusioncharts relies on the fusioncharts module, which have also been installed. We imported the necessary modules and resolved their dependencies, instructed Vue to use the wrapper globally (throughout the project) in the src/main.js file, and therefore there is no lack of definition for the custom <fusioncharts> component that we have used here. Also, the custom component has custom attributes, and each of the custom attribute is bound to a data object (and in turn, their values), by the v-bind directive, for which the shorthand is the colon (:) symbol. We will learn about the attributes and their associated data objects in a greater detail, when we discuss some of the specific charts used in this project.
In the <script>, first you declare the props that the component is supposed to receive, and then go on defining the data objects that are bounded to the attributes of <fusioncharts>. The values assigned to the data objects are the values that the attributes of <fusioncharts> pulls in, and the charts are created on the basis of those pulled in values. Apart from these, the most interesting part of the code is the watch { } object. This is a very special object in Vue’s scheme of things — it essentially instructs Vue to watch over any changes happening to certain data, and then take actions based on how the handler function for that data has been defined. For example, we want Vue to keep a watch on the prop received, i.e., data_prop_received_by_the_component in the pseudocode. The prop becomes a key in the watch { } object, and the value of the key is another object — a handler method that describes what needs to be done whenever the prop changes. With such elegant mechanisms to handle the changes, the app maintains its reactivity. The deep: true represents a boolean flag that you can associate with watchers, so that the object being watched is watched rather deeply, i.e., even the changes made in the nested levels of the object are tracked. (For more information on watchers, consult the official documentation).
Now that you are equipped with an understanding of the general scheme of things, let’s dive into the specific implementations of the charts in the .vue component files. The code will be pretty self-explanatory, and you should try to understand how the specifics fit in the general scheme of things described above.
Implementation Of Charts In .vue Files
While the very specifics of the implementation varies from one chart to another, the following explanation is applicable for all of them:
<template> As explained previously, the <fusioncharts> custom component has several attributes, each of them being bound to corresponding data object defined in the data() function by using the v-bind: directive. The attribute names are quite self-explanatory for what they mean, and figuring out the corresponding data objects is also trivial.
<script> In the data() function, the data objects and their values are what makes the charts work, because of the binding done by the v-bind (:) directives used on the attributes of <fusioncharts>. Before we dive deep into the individual data objects, it’s worth mentioning some general characteristics:
The data objects whose values are either 0 or 1 are boolean in nature, where 0 represents something not available/turned off, and 1 represents availability/turned on state. However, be cautious that non-boolean data objects can also have 0 or 1 as their values, besides other possible values — it depends on the context. For example, containerbackgroundopacity with its default value as 0 is boolean, whereas lowerLimit with its default value as 0 simply means the number zero is its literal value.
Some data objects deals with CSS properties like margin, padding, font-size, etc. — the value has an implied unit of “px” or pixel. Similarly, other data objects can have implicit units associated with their values. For detailed information, please refer to the respective chart attributes page of FusionCharts Dev Center.
In the data() function, perhaps the most interesting and non-obvious object is the dataSource. This object has three main objects nested within it:
chart: This object encapsulates lots of chart attributes related to the configuration and cosmetics of the chart. It is almost a compulsory construct that you will find in all the charts you will create for this project.
colorrange: This object is somewhat specific to the chart under consideration, and is mainly present in charts that deals with multiple colors/shades to demarcate different sub-ranges of the scale used in chart.
value: This object, again, is present in charts that has a specific value that needs to be highlighted in the range of the scale.
The watch { } object is perhaps the most crucial thing that makes this chart, and the other charts used in this project, spring to life. The reactivity of the charts, i.e., the charts updating themselves based on the new values resulting from a new user query is controlled by the watchers defined in this object. For example, we have defined a watcher for the prop highlights received by the component, and then defined a handler function to instruct Vue about the necessary actions that it should take, when anything changes about the object being watched in the entire project. This means that whenever App.vue yields a new value for any of the object within highlights, the information trickles down all the way down to this component, and the new value is updated in the data objects of this component. The chart being bound to the values, also gets updated as a result of this mechanism.
The above explanations are quite broad strokes to help us develop an intuitive understanding of the bigger picture. Once you understand the concepts intuitively, you can always consult the documentation of Vue.js and FusionCharts, when something is not clear to you from the code itself. We leave the exercise to you, and from the next subsection onward, we will not explain stuff that we covered in this subsection.
src/components/TempVarChart.vue
(Large preview)
<template> <div class="custom-card header-card card"> <div class="card-body pt-0"> <fusioncharts type="spline" width="100%" height="100%" dataformat="json" dataEmptyMessage="i-https://i.postimg.cc/R0QCk9vV/Rolling-0-9s-99px.gif" dataEmptyMessageImageScale=39 :datasource="tempChartData" > </fusioncharts> </div> </div> </template> <script> export default { props: ["tempVar"], components: {}, data() { return { tempChartData: { chart: { caption: "Hourly Temperature", captionFontBold: "0", captionFontColor: "#000000", captionPadding: "30", baseFont: "Roboto", chartTopMargin: "30", showHoverEffect: "1", theme: "fusion", showaxislines: "1", numberSuffix: "°C", anchorBgColor: "#6297d9", paletteColors: "#6297d9", drawCrossLine: "1", plotToolText: "$label<br><hr><b>$dataValue</b>", showAxisLines: "0", showYAxisValues: "0", anchorRadius: "4", divLineAlpha: "0", labelFontSize: "13", labelAlpha: "65", labelFontBold: "0", rotateLabels: "1", slantLabels: "1", canvasPadding: "20" }, data: [], }, }; }, methods: { setChartData: function() { var data = []; for (var i = 0; i < this.tempVar.tempToday.length; i++) { var dataObject = { label: this.tempVar.tempToday[i].hour, value: this.tempVar.tempToday[i].temp }; data.push(dataObject); } this.tempChartData.data = data; }, }, mounted: function() { this.setChartData(); }, watch: { tempVar: { handler: function() { this.setChartData(); }, deep: true }, }, }; </script> <style> </style>
src/components/UVIndex.vue
This component contains an extremely useful chart — the Angular Gauge.
(Large preview)
The code for the component is given below. For detailed information on the chart attributes of Angular Gauge, refer to FusionCharts Dev Center page for Angular Gauge.
<template> <div class="highlights-item col-md-4 col-sm-6 col-xs-12 border-top"> <div> <fusioncharts :type="type" :width="width" :height="height" :containerbackgroundopacity="containerbackgroundopacity" :dataformat="dataformat" :datasource="datasource" ></fusioncharts> </div> </div> </template> <script> export default { props: ["highlights"], components: {}, data() { return { type: "angulargauge", width: "100%", height: "100%", containerbackgroundopacity: 0, dataformat: "json", datasource: { chart: { caption: "UV Index", captionFontBold: "0", captionFontColor: "#000000", captionPadding: "30", lowerLimit: "0", upperLimit: "15", lowerLimitDisplay: "1", upperLimitDisplay: "1", showValue: "0", theme: "fusion", baseFont: "Roboto", bgAlpha: "0", canvasbgAlpha: "0", gaugeInnerRadius: "75", gaugeOuterRadius: "110", pivotRadius: "0", pivotFillAlpha: "0", valueFontSize: "20", valueFontColor: "#000000", valueFontBold: "1", tickValueDistance: "3", autoAlignTickValues: "1", majorTMAlpha: "20", chartTopMargin: "30", chartBottomMargin: "40" }, colorrange: { color: [ { minvalue: "0", maxvalue: this.highlights.uvIndex.toString(), code: "#7DA9E0" }, { minvalue: this.highlights.uvIndex.toString(), maxvalue: "15", code: "#D8EDFF" } ] }, annotations: { groups: [ { items: [ { id: "val-label", type: "text", text: this.highlights.uvIndex.toString(), fontSize: "20", font: "Source Sans Pro", fontBold: "1", fillcolor: "#212529", x: "$gaugeCenterX", y: "$gaugeCenterY" } ] } ] }, dials: { dial: [ { value: this.highlights.uvIndex.toString(), baseWidth: "0", radius: "0", borderThickness: "0", baseRadius: "0" } ] } } }; }, methods: {}, computed: {}, watch: { highlights: { handler: function() { this.datasource.colorrange.color[0].maxvalue = this.highlights.uvIndex.toString(); this.datasource.colorrange.color[1].minvalue = this.highlights.uvIndex.toString(); this.datasource.annotations.groups[0].items[0].text = this.highlights.uvIndex.toString(); }, deep: true } } }; </script>
src/components/Visibility.vue
In this component, we use a Horizontal Linear Gauge to represent the visibility, as shown in the image below:
(Large preview)
The code for the component is given below. For an in depth understanding of the different attributes of this chart type, please refer to FusionCharts Dev Center page for Horizontal Linear Gauge.
<template> <div class="highlights-item col-md-4 col-sm-6 col-xs-12 border-left border-right border-top"> <div> <fusioncharts :type="type" :width="width" :height="height" :containerbackgroundopacity="containerbackgroundopacity" :dataformat="dataformat" :datasource="datasource" > </fusioncharts> </div> </div> </template> <script> export default { props: ["highlights"], components: {}, methods: {}, computed: {}, data() { return { type: "hlineargauge", width: "100%", height: "100%", containerbackgroundopacity: 0, dataformat: "json", creditLabel: false, datasource: { chart: { caption: "Air Visibility", captionFontBold: "0", captionFontColor: "#000000", baseFont: "Roboto", numberSuffix: " km", lowerLimit: "0", upperLimit: "40", showPointerShadow: "1", animation: "1", transposeAnimation: "1", theme: "fusion", bgAlpha: "0", canvasBgAlpha: "0", valueFontSize: "20", valueFontColor: "#000000", valueFontBold: "1", pointerBorderAlpha: "0", chartBottomMargin: "40", captionPadding: "30", chartTopMargin: "30" }, colorRange: { color: [ { minValue: "0", maxValue: "4", label: "Fog", code: "#6297d9" }, { minValue: "4", maxValue: "10", label: "Haze", code: "#7DA9E0" }, { minValue: "10", maxValue: "40", label: "Clear", code: "#D8EDFF" } ] }, pointers: { pointer: [ { value: this.highlights.visibility.toString() } ] } } }; }, watch: { highlights: { handler: function() { this.datasource.pointers.pointer[0].value = this.highlights.visibility.toString(); }, deep: true } } }; </script>
src/components/WindStatus.vue
This component displays the wind speed and direction (wind velocity, if you are physics savvy), and it is very difficult to represent a vector using a chart. For such cases, we suggest representing them with the aid of some nice images and text values. Since the representation we have thought about is entirely dependent on CSS, we will implement it in the next section that deals with the CSS. However, take a look at what we are aiming to create:
(Large preview)
<template> <div class="highlights-item col-md-4 col-sm-6 col-xs-12 border-top"> <div> <div class="card-heading pt-5">Wind Status</div> <div class="row pt-4 mt-4"> <div class="col-sm-6 col-md-6 mt-2 text-center align-middle"> <p class="card-sub-heading mt-3">Wind Direction</p> <p class="mt-4"><img src="../assets/winddirection.svg" height="40" width="40"></p> <p class="card-value mt-4"></p> </div> <div class="col-sm-6 col-md-6 mt-2"> <p class="card-sub-heading mt-3">Wind Speed</p> <p class="mt-4"><img src="../assets/windspeed.svg" height="40" width="40"></p> <p class="card-value mt-4"> km/h</p> </div> </div> </div> </div> </template> <script> export default { props: ["highlights"], components: {}, data() { return {}; }, methods: {}, computed: {} }; </script>
Wrapping Up With Highlights.vue
Recall that we have already implemented code with CSS for all the components — except Content.vue and Highlights.vue. Since Content.vue is a dumb component that just relays data, the minimal styling it needs has already been covered. Also, we have already written appropriate code for styling the sidebar and the cards containing the charts. Therefore, all we are left to do is add some stylistic bits to Highlights.vue, which primarily involves using the CSS classes:
<template> <div class="custom-content-card content-card card"> <div class="card-body pb-0"> <div class="content-header h4 text-center pt-2 pb-3">Highlights</div> <div class="row"> <uv-index :highlights="highlights"></uv-index> <visibility :highlights="highlights"></visibility> <wind-status :highlights="highlights"></wind-status> </div> </div> </div> </template> <script> import UVIndex from "./UVIndex.vue"; import Visibility from "./Visibility.vue"; import WindStatus from "./WindStatus.vue"; export default { props: ["highlights"], components: { "uv-index": UVIndex, "visibility": Visibility, "wind-status": WindStatus, }, }; </script>
Deployment And Source Code
With the charts and style in order, we are done! Take a moment to appreciate the beauty of your creation.

(Large preview)
It’s now time for you to deploy your application, and share it with your peers. If you don’t have much idea about deployment and expect us to help you, look here about our take on deployment ideas. The linked article also contains suggestions on how to remove the FusionCharts watermark at the left bottom of every chart.
If you mess up somewhere and want a reference point, the source code is available on Github.
(ms, ra, il)
0 notes
Text
The Shortcut to Becoming a Full Stack Developer
Hello everyone. Becoming a full-stack developer may sound like a daunting task, but it doesn't have to be a long and winding road.

Step 1: Set clear goals.
Before you embark on your journey, it's important to set clear goals. Define what kind of full-stack developer you want to be.
Step 2: Learn the Basics
To be a full-stack developer, you need a solid foundation in both front-end and back-end development. Start with the basics:
1.HTML and CSS: Learn how to create and style web pages. These are the building blocks of front-end development.
2.JavaScript: This is the language of the web. Learn the fundamentals of JavaScript, as it's essential for front-end development.
3.Server-side Language: Choose a server-side language like Python, Ruby, or Node.js. This will be your gateway to back-end development.
4.Databases: Understand the basics of databases, including SQL and NoSQL.
Step 3: Build Projects
The best way to learn is by doing. Start building projects that incorporate what you've learned. Create a personal website, a simple blog, or a to-do list app. This hands-on experience is invaluable and will help you gain practical skills.
Step 4: Explore Frameworks and Libraries
To become more efficient and competitive, start exploring popular front-end and back-end frameworks and libraries. For example:
Front-end: React, Angular, or Vue.js for building interactive and dynamic web applications.
Back-end: Express.js, Django, or Ruby on Rails for efficient server-side development.
Step 5: Version Control
Familiarize yourself with version control systems like Git. It's a crucial skill for collaboration and code management.
Step 6: Learn DevOps Basics
Understand the basics of DevOps, which includes deployment, continuous integration, and containerization (e.g., Docker). These skills make you more versatile as a developer.
Step 7: Specialize
Once you've mastered the fundamentals, you can choose to specialize in a specific area, such as mobile app development, machine learning, or cybersecurity.
Step 8: Keep Learning
Technology evolves rapidly. Stay up-to-date with the latest trends, tools, and best practices in the field. Online courses, tutorials, and books are excellent resources for continuous learning.
Step 9: Build a Portfolio
Create a portfolio showcasing the projects you've worked on. This will help you stand out when applying for jobs or freelance work.
Step 10: Network and Apply for Jobs
Connect with other developers, attend meetups, and join online forums. Networking can lead to job opportunities. Start applying for full-stack developer positions or freelance gigs.

To become a full-stack developer, I highly recommend ACTE Technologies. ACTE Technologies is a trusted provider of IT training and certification programs, including specialized full-stack developer training with career guidance. Whether you're aiming to boost your career or dive into the world of development, ACTE Technologies can be your partner on the path to full-stack developer training expertise. Good luck on your path to full-stack development!
Thank you!
0 notes